Reactjs 反应谷歌地图车辆实时跟踪

Reactjs 反应谷歌地图车辆实时跟踪,reactjs,react-hooks,fetch,react-google-maps,Reactjs,React Hooks,Fetch,React Google Maps,我正试图通过从api端点获取数据来移动带有deviceId的选定标记。在第一次渲染时,我获取最近1分钟的cordinates数据,并将cordinates放入声明为Path的空数组中,每30秒后,我运行一个setinterval函数,该函数每30秒获取最近30秒的数据,并将cordinates放入Path数组中。以下代码可以提供一些想法: import { withGoogleMap, withScriptjs, GoogleMap, Polyline, Marker } f

我正试图通过从api端点获取数据来移动带有deviceId的选定标记。在第一次渲染时,我获取最近1分钟的cordinates数据,并将cordinates放入声明为Path的空数组中,每30秒后,我运行一个setinterval函数,该函数每30秒获取最近30秒的数据,并将cordinates放入Path数组中。以下代码可以提供一些想法:

import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  Polyline,
  Marker
} from "react-google-maps";
const mapStyles = require("./mapStyles.json");


const Map = ({deviceId}) =>  {
  const [progress, setProgress]= useState()  
  const path= []

  const getInitialPositions = async () => {
    let from = new Date()
    let milliseconds = Date.parse(from)
    milliseconds = milliseconds - (1* 60 * 1000)
    from = new Date(milliseconds).toISOString()
    console.log(from)
    const to = new Date().toISOString()
    console.log(to)
    const response = await fetch(`/api/positions/?deviceId=${37}&from=${from}&to=${to}`, {
      headers: {
        'Accept': 'application/json' 
      }
    })
      const items = await response.json()
    
      console.log(items)
      items.map( item => { 
        path.push({lat: item.latitude, lng: item.longitude})
        return path
      })   
      console.log(path)
  };

  const getPositions30Seconds = async () => {
    let from = new Date()
    let milliseconds = Date.parse(from)
    milliseconds = milliseconds - (0.5* 60 * 1000)
    from = new Date(milliseconds).toISOString()
    console.log(from)
    const to = new Date().toISOString()
    console.log(to)
    const response = await fetch(`/api/positions/?deviceId=14&from=${from}&to=${to}`, {
      headers: {
        'Accept': 'application/json' 
      }
    })
      const items = await response.json()
      console.log(items)
      items.map( item => { 
        path.push({lat: item.latitude, lng: item.longitude})
        return path
      })   
      console.log(path)
  };

  useEffect (() => {
    const interval = window.setInterval(getPositions30Seconds,30000)
    return () => {
      window.clearInterval(interval)
    }
  },[]);

  useEffect(()=>{
    getInitialPositions()  
  },[])
  
    const icon = {
        url: '/images/icon/car.png',
        scaledSize: new window.google.maps.Size(30, 30),
        anchor: { x: 10, y: 10 }
      };
      return (
        <GoogleMap
          defaultZoom={4}
          defaultCenter={path[path.length-1]}
          defaultOptions={{ styles: mapStyles, fullscreenControl: false, mapTypeControl: false, streetViewControl: false}}
        >
        {progress && (
          <>
            <Polyline
              path={progress}
              options={{ strokeColor: "light" }}
            />
            
            <Marker
              icon={icon}  
              position={progress[progress.length - 1]}  
            />

          </>
        )}
    
        </GoogleMap>
      );
    };


const MapComponent = withScriptjs(withGoogleMap(Map))

export default () => (
  <MapComponent
    googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLEMAP_KEY}&v=3.exp&libraries=geometry,drawing,places`}
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `100%`, width: '100%' }} />}
    mapElement={<div style={{ height: `100%` }} />}
  />
)

导入{
用谷歌地图,
用ScriptJS,
谷歌地图,
多段线,
标记
}从“谷歌地图反应”;
const-mapStyles=require(“./mapStyles.json”);
常量映射=({deviceId})=>{
const[progress,setProgress]=useState()
常量路径=[]
const getInitialPositions=async()=>{
let from=新日期()
让毫秒=Date.parse(from)
毫秒=毫秒-(1*60*1000)
from=新日期(毫秒)。toISOString()
console.log(来自)
const to=new Date().toISOString()
console.log(到)
const response=wait fetch(`/api/positions/?deviceId=${37}&from=${from}&to=${to}`{
标题:{
“接受”:“应用程序/json”
}
})
const items=wait response.json()
console.log(项目)
items.map(item=>{
push({lat:item.latitude,lng:item.longitude})
返回路径
})   
console.log(路径)
};
const getPositions30Seconds=async()=>{
let from=新日期()
让毫秒=Date.parse(from)
毫秒=毫秒-(0.5*60*1000)
from=新日期(毫秒)。toISOString()
console.log(来自)
const to=new Date().toISOString()
console.log(到)
const response=wait fetch(`/api/positions/?deviceId=14&from=${from}&to=${to}`{
标题:{
“接受”:“应用程序/json”
}
})
const items=wait response.json()
console.log(项目)
items.map(item=>{
push({lat:item.latitude,lng:item.longitude})
返回路径
})   
console.log(路径)
};
useffect(()=>{
const interval=window.setInterval(获取位置30秒,30000)
return()=>{
窗口清除间隔(间隔)
}
},[]);
useffect(()=>{
getInitialPositions()
},[])
常量图标={
url:“/images/icon/car.png”,
scaledSize:newwindow.google.maps.Size(30,30),
主播:{x:10,y:10}
};
返回(
{进展&&(
)}
);
};
常量MapComponent=withScriptjs(withGoogleMap(Map))
导出默认值()=>(
)
我想使用这个路径数组,就像下面提到的类组件一样,它有一个静态的路径数组数据

import React from "react";
import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  Polyline,
  Marker
} from "react-google-maps";
const mapStyles = require("./mapStyles.json");

class Map extends React.Component {
  state = {
    progress: [],
    selectedMarker: false
  };

  path = [
    { lat: 28.539533333333335, lng: 77.05334444444445},
     {lat: 28.539581666666667, lng: 77.05323333333334},
     {lat: 28.539614999999998, lng: 77.05313333333334},
     {lat: 28.539766666666665, lng: 77.05258166666667},
     {lat: 28.539884444444443, lng: 77.05252666666667},
     {lat: 28.539884444444443, lng: 77.05252666666667},
     {lat: 28.542425, lng: 77.05253666666667},
     {lat: 28.544408333333333, lng: 77.05254333333333},
     {lat: 28.544445, lng: 77.052655},
     {lat: 28.544383333333332, lng: 77.05419333333333},
     {lat: 28.544383333333332, lng: 77.05419333333333},
     {lat: 28.544383333333332, lng: 77.05419333333333},
     {lat: 28.544383333333332, lng: 77.05419333333333},
     {lat: 28.544383333333332, lng: 77.05419333333333},
     {lat: 28.544439999999998, lng: 77.05512},
     {lat: 28.544561666666667, lng: 77.055295},
     {lat: 28.546363333333336, lng: 77.05680833333334},
     {lat: 28.54712166666667, lng: 77.05741277777777},
     {lat: 28.547226666666667, lng: 77.05737},
     {lat: 28.54752166666667, lng: 77.05704},
     {lat: 28.54752166666667, lng: 77.05704},
     {lat: 28.54752166666667, lng: 77.05704},
     {lat: 28.54752166666667, lng: 77.05704},
     {lat: 28.54752166666667, lng: 77.05704},
     {lat: 28.547706666666667, lng: 77.05692833333333},
     {lat: 28.548081666666665, lng: 77.05644666666666},
     {lat: 28.548235000000002, lng: 77.05629},
     {lat: 28.548235000000002, lng: 77.05629},
     {lat: 28.548571666666668, lng: 77.05574333333333},
     {lat: 28.548655, lng: 77.05571166666667},
     {lat: 28.548745, lng: 77.05563666666667},
     {lat:28.55049, lng: 77.05438},
     {lat: 28.550714999999997, lng: 77.05413666666666},
     {lat: 28.55175, lng: 77.05356833333333},
     {lat: 28.553496666666668, lng: 77.05223166666667},
     {lat: 28.553915, lng: 77.05173833333333 }
];

  velocity = 50;
  initialDate = new Date();

  getDistance = () => {
    // seconds between when the component loaded and now
    const differentInTime = (new Date() - this.initialDate) / 8000; // pass to seconds
    return differentInTime * this.velocity; 
  };

  componentDidMount = () => {
    this.interval = window.setInterval(this.moveObject, 100);
  };

  handleClick = (marker, event) => {
    // console.log({ marker })
    this.setState({ selectedMarker: marker })
  }

  componentWillUnmount = () => {
    window.clearInterval(this.interval);
  };

  moveObject = () => {
    const distance = this.getDistance();
     if (!distance) {
      return;
    }

    let progress = this.path.filter(
      coordinates => coordinates.distance < distance
    );

    const nextLine = this.path.find(
      coordinates => coordinates.distance > distance
    );
    if (!nextLine) {
      this.setState({ progress });
      return; // it's the end!
    }
    const lastLine = progress[progress.length - 1];

    const lastLineLatLng = new window.google.maps.LatLng(
      lastLine.lat,
      lastLine.lng
    );

    const nextLineLatLng = new window.google.maps.LatLng(
      nextLine.lat,
      nextLine.lng
    );

    // distance of this line
    const totalDistance = nextLine.distance - lastLine.distance;
    const percentage = (distance - lastLine.distance) / totalDistance;

    const position = window.google.maps.geometry.spherical.interpolate(
      lastLineLatLng,
      nextLineLatLng,
      percentage
    );

    progress = progress.concat(position);
    this.setState({ progress });
  };

  componentWillMount = () => {
    this.path = this.path.map((coordinates, i, array) => {
      if (i === 0) {
        return { ...coordinates, distance: 0 }; // it begins here!
      }
      const { lat: lat1, lng: lng1 } = coordinates;
      const latLong1 = new window.google.maps.LatLng(lat1, lng1);

      const { lat: lat2, lng: lng2 } = array[0];
      const latLong2 = new window.google.maps.LatLng(lat2, lng2);

      // in meters:
      const distance = window.google.maps.geometry.spherical.computeDistanceBetween(
        latLong1,
        latLong2
      );

      return { ...coordinates, distance };
    });

    console.log(this.path);
  };

  componentDidUpdate = () => {
    const distance = this.getDistance();
    if (!distance) {
      return;
    }

    let progress = this.path.filter(
      coordinates => coordinates.distance < distance
    );

    const nextLine = this.path.find(
      coordinates => coordinates.distance > distance
    );

    let point1, point2;

    if (nextLine) {
      point1 = progress[progress.length - 1];
      point2 = nextLine;
    } else {
      // it's the end, so use the latest 2
      point1 = progress[progress.length - 2];
      point2 = progress[progress.length - 1];
    }

    const point1LatLng = new window.google.maps.LatLng(point1.lat, point1.lng);
    const point2LatLng = new window.google.maps.LatLng(point2.lat, point2.lng);

    const angle = window.google.maps.geometry.spherical.computeHeading(
      point1LatLng,
      point2LatLng
    );
    const actualAngle = angle - 35;

    const markerUrl =
    '/images/icon/car.png'
    const item = document.querySelector(`[src="${markerUrl}"]`);

    if (item) {
      // when it hasn't loaded, it's null
      item.style.transform = `rotate(${actualAngle}deg)`;
    }
  };

  render = () => {
    const icon = {
        url: '/images/icon/car.png',
        scaledSize: new window.google.maps.Size(35, 35),
        anchor: { x: 10, y: 10 }
      };
    return (
        <GoogleMap
          defaultZoom={18}
          defaultCenter={{lat: 28.539766666666665, lng: 77.05258166666667}}
          defaultOptions={{ 
              styles: mapStyles, 
              fullscreenControl: false, 
              mapTypeControl: false, 
              streetViewControl: false,
            }}
        >
        {this.state.progress && (
          <>
            <Polyline
              path={this.state.progress}
              options={{ strokeColor: "gray" }}
            />
            
            <Marker
              icon={icon}  
              position={this.state.progress[this.state.progress.length - 1]}  
            />

          </>
        )}
      </GoogleMap>
    );
  };
}

const MapComponent = withScriptjs(withGoogleMap(Map));

export default () => (
    <MapComponent
    googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLEMAP_KEY}&v=3.exp&libraries=geometry,drawing,places`}
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `100%`, width: '100%' }} />}
    mapElement={<div style={{ height: `100%` }} />}
    />
  )

从“React”导入React;
进口{
用谷歌地图,
用ScriptJS,
谷歌地图,
多段线,
标记
}从“谷歌地图反应”;
const-mapStyles=require(“./mapStyles.json”);
类映射扩展了React.Component{
状态={
进展:[],
selectedMarker:false
};
路径=[
{拉丁美洲:28.539533335,液化天然气:77.05334445},
{拉丁美洲:28.53958166667,液化天然气:77.05323333334},
{拉丁美洲:28.5396149999998,液化天然气:77.05313334},
{拉丁美洲:28.5397665,液化天然气:77.052581667},
{拉丁美洲:28.53988444443,液化天然气:77.0525266667},
{拉丁美洲:28.53988444443,液化天然气:77.0525266667},
{拉丁美洲:28.542425,液化天然气:77.052536667},
{拉丁美洲:28.544408333333,液化天然气:77.052543333},
{lat:28.544445,lng:77.052655},
{拉丁美洲:28.5443833332,液化天然气:77.05419333333},
{拉丁美洲:28.5443833332,液化天然气:77.05419333333},
{拉丁美洲:28.5443833332,液化天然气:77.05419333333},
{拉丁美洲:28.5443833332,液化天然气:77.05419333333},
{拉丁美洲:28.5443833332,液化天然气:77.05419333333},
{拉丁美洲:28.54443999998,液化天然气:77.05512},
{拉丁美洲:28.54456667,液化天然气:77.055295},
{拉丁美洲:28.54633336,液化天然气:77.0568083334},
{拉丁美洲:28.5471216666667,液化天然气:77.0574127777},
{拉丁美洲:28.5472266666667,液化天然气:77.05737},
{拉丁美洲:28.5475216666667,液化天然气:77.05704},
{拉丁美洲:28.5475216666667,液化天然气:77.05704},
{拉丁美洲:28.5475216666667,液化天然气:77.05704},
{拉丁美洲:28.5475216666667,液化天然气:77.05704},
{拉丁美洲:28.5475216666667,液化天然气:77.05704},
{拉丁美洲:28.547706666667,液化天然气:77.0569283333333},
{拉丁美洲:28.54808166665,液化天然气:77.0564466666},
{拉脱维亚:28.54823500000002,液化天然气:77.05629},
{拉脱维亚:28.54823500000002,液化天然气:77.05629},
{拉丁美洲:28.54857166668,液化天然气:77.05574333333},
{拉丁美洲:28.548655,液化天然气:77.05571166667},
{拉丁美洲:28.548745,液化天然气:77.0556366667},
{lat:28.55049,lng:77.05438},
{拉丁美洲:28.5507149999997,液化天然气:77.0541366666},
{拉丁美洲:28.55175,液化天然气:77.05356833333},
{拉丁美洲:28.55349666668,液化天然气:77.0522316667},
{拉丁美洲:28.553915,液化天然气:77.05173833333}
];
速度=50;
initialDate=新日期();
getDistance=()=>{
//加载组件时与现在之间的秒数
const differentInTime=(new Date()-this.initialDate)/8000;//传递到秒
返回differentintTime*this.velocity;
};
componentDidMount=()=>{
this.interval=window.setInterval(this.moveObject,100);
};
handleClick=(标记,事件)=>{
//console.log({marker})
this.setState({selectedMarker:marker})
}
组件将卸载=()=>{
window.clearInterval(this.interval);
};
moveObject=()=>{
常量距离=this.getDistance();
如果(!距离){
返回;
}
让progress=this.path.filter(
坐标=>坐标.距离<距离
);
const nextLine=this.path.find(
坐标=>坐标.距离>距离
);
如果(!nextLine){
this.setState({progress});
return;//结束了!
}
const lastLine=progress[progress.length-1];
const lastLineLatLng=new window.google.maps.LatLng(