Google Mapsで遊んで、反応してください-Useのように、道を通って車移動をしてください-パート1


あなたがOverで働くエンジニアであるふりをしましょう.あなたは、その目的地に到達すると、道路を移動する車をアニメーション化するタスクを持っている.それで、あなたは反応を使用するつもりです.ハウツーとスタイル

当社のツール


このガイドのために、私は創造的な反応アプリを使用するつもりですreact-google-maps , これはGoogleマップライブラリのラッパーです.npm install react-google-maps

基本図


基本的な地図から始めましょう.Googleマップライブラリは次のように初期化できます.
import React from 'react';
import { withGoogleMap, withScriptjs, GoogleMap } from 'react-google-maps'

class Map extends React.Component {
  render = () => {
    return (
      <GoogleMap
        defaultZoom={16}
        defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
        >
      </GoogleMap>
    )
  }
}

const MapComponent = withScriptjs(withGoogleMap(Map))

export default () => (
  <MapComponent
  googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
  loadingElement={<div style={{ height: `100%` }} />}
  containerElement={<div style={{ height: `400px`, width: '500px' }} />}
  mapElement={<div style={{ height: `100%` }} />}
  />
)
私は初期化の詳細には行かないreact-google-maps , しかし、代わりに、私は運動のために論理に集中します.あなたはそれを設定する方法を学びたい場合は、することができますread their guide .
私が使っている主な小道具はdefaultZoom , Googleマップのズームを設定します.ズームが高いほど、地面に接近し、defaultCenter , これはマップの主な位置情報を設定します.
それはプンタカナイのラウンドアバウト(私が住んでいるところに近い)で基本的なマップをロードする必要があります.

緯度と経度


地図を描く前に、緯度と経度を理解する必要があります.緯度と経度は、地理的な位置を表す単位です.緯度数は90から90まで、0は赤道であり、経度数は180から180まで、0はプライマー子午線である.
基本的には、緯度では、中央に赤道を使用して垂直方向の位置を制御すると、経度を使用して、水平方向の位置を制御すると、中央の主要な経絡と.
あなたは本当にGoogleマップを(Googleのおかげで)を操作するためにどのように座標作業を理解する必要はありません!Googleは、距離を測定するためのツールを提供し、オブジェクトが直面している場所を計算し、あなただけの座標を渡します.あなたが深く掘ることに興味があるならば、あなたはより多くを読むことができますWikipedia's article .

マーカー


マーカーは、地図上の場所を識別し、通常すべての場所に知っているアイコンを使用しています:

マーカーは、その緯度と経度を知って、特定の場所に配置することができます.次のようにロータリーの真ん中にマーカーを置くことができます.
import React from 'react';
import { withGoogleMap, withScriptjs, GoogleMap, Marker } from 'react-google-maps'

class Map extends React.Component {
  render = () => {
    return (
      <GoogleMap
        defaultZoom={16}
        defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
        >
          <Marker position={{
            lat: 18.559024,
            lng: -68.388886,
          }} />
      </GoogleMap>
    )
  }
}

const MapComponent = withScriptjs(withGoogleMap(Map))

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

ポリライン


polylineコンポーネントは、path prop.我々は直線の2つの座標を使用することができます.
import React from "react";
import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  Polyline
} from "react-google-maps";

class Map extends React.Component {
  path = [
    { lat: 18.55996, lng: -68.388832 },
    { lat: 18.558028, lng: -68.388971 }
  ];
  render = () => {
    return (
      <GoogleMap
        defaultZoom={16}
        defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
      >
        <Polyline path={this.path} options={{ strokeColor: "#FF0000 " }} />
      </GoogleMap>
    );
  };
}

const MapComponent = withScriptjs(withGoogleMap(Map));

export default () => (
  <MapComponent
    googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `400px`, width: "500px" }} />}
    mapElement={<div style={{ height: `100%` }} />}
  />
);

我々は、ちょうどラウンドアバウトを横切って直線を描きました!私は運転中にこれを行うことをお勧めしません.
しかし、曲線線はどうですか?まあ、悪いニュースがある.曲線は存在しません.彼らはあなたに曲線があるという幻想を与えて、一緒にまっすぐな線の束です.場合は十分にズーム、彼らは常に目に見えるようになります.それで、十分な座標を加えることによって、カーブを作りましょう.
import React from "react";
import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  Polyline
} from "react-google-maps";

class Map extends React.Component {
  path = [
    { lat: 18.558908, lng: -68.389916 },
    { lat: 18.558853, lng: -68.389922 },
    { lat: 18.558375, lng: -68.389729 },
    { lat: 18.558032, lng: -68.389182 },
    { lat: 18.55805, lng: -68.388613 },
    { lat: 18.558256, lng: -68.388213 },
    { lat: 18.558744, lng: -68.387929 }
  ];
  render = () => {
    return (
      <GoogleMap
        defaultZoom={16}
        defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
      >
        <Polyline path={this.path} options={{ strokeColor: "#FF0000 " }} />
      </GoogleMap>
    );
  };
}

const MapComponent = withScriptjs(withGoogleMap(Map));

export default () => (
  <MapComponent
    googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `400px`, width: "500px" }} />}
    mapElement={<div style={{ height: `100%` }} />}
  />
);

そして、それはあなたが曲線を描く方法です!さらに多くの座標を追加することで、我々は直線をより顕著にすることができます.

アニメーション化


これは楽しみが始まるところです.マーカーの最後にマーカーを追加しましょうpath . それは我々の車とそれが進行した道を表します.
import React from "react";
import {
  withGoogleMap,
  withScriptjs,
  GoogleMap,
  Polyline,
  Marker
} from "react-google-maps";

class Map extends React.Component {
  path = [
    { lat: 18.558908, lng: -68.389916 },
    { lat: 18.558853, lng: -68.389922 },
    { lat: 18.558375, lng: -68.389729 },
    { lat: 18.558032, lng: -68.389182 },
    { lat: 18.55805, lng: -68.388613 },
    { lat: 18.558256, lng: -68.388213 },
    { lat: 18.558744, lng: -68.387929 }
  ];
  render = () => {
    return (
      <GoogleMap
        defaultZoom={16}
        defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
      >
        <Polyline path={this.path} options={{ strokeColor: "#FF0000 " }} />
        <Marker position={this.path[this.path.length - 1]} />
      </GoogleMap>
    );
  };
}

const MapComponent = withScriptjs(withGoogleMap(Map));

export default () => (
  <MapComponent
    googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `400px`, width: "500px" }} />}
    mapElement={<div style={{ height: `100%` }} />}
  />
);

今、我々はアニメーションのロジックを準備する必要があります.我々は直線の束を持っており、我々は道の中に車を配置する必要があります.私たちは4ステップにロジックをsepareことができます.
  • 最初の点と各座標の間の距離を計算します.これは、パス内の座標を順序とする.
  • 速度を設定し、車が時間をかけて進行している距離を計算します.
  • 計算距離を使用して、我々は完全なパスを使用することができますし、車が通過したパスを取得します.
  • アニメーションは、最後の直線は、ここでは、車が現在です.
  • 距離の計算


    Googleは2つの座標間の距離を計算するツールを提供します.問題の関数はgoogle.maps.geometry.spherical.computeDistanceBetweenコンポーネントをマウントする前にこの手順を実行できます.各座標とパスの最初の要素の間の距離を計算します.
      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)
      }
    
    

    速度を設定し、毎秒の距離を計算します。


    今物理学に.我々のオブジェクトが1秒につき5メートル行くことを望むと言いましょう.そのためには、初期値と速度が必要です.コンソールしましょう.毎秒この距離を記録してください.
      velocity = 5
      initialDate = new Date()
    
      getDistance = () => {
        // seconds between when the component loaded and now
        const differentInTime = (new Date() - this.initialDate) / 1000 // pass to seconds
        return differentInTime * this.velocity // d = v*t -- thanks Newton!
      }
    
      componentDidMount = () => {
        this.interval = window.setInterval(this.consoleDistance, 1000)
      }
    
      componentWillUnmount = () => {
        window.clearInterval(this.interval)
      }
    
      consoleDistance = () => {
        console.log(this.getDistance())
      }
    
    これはコンソールになります.私たちの車の速度と同じように5秒ごとに増加数を記録します.
    一緒に、または現在の進捗状況をまとめましょう
    import React from 'react';
    import { withGoogleMap, withScriptjs, GoogleMap, Polyline, Marker } from 'react-google-maps'
    
    class Map extends React.Component {
      path = [
        { lat: 18.558908, lng: -68.389916 },
        { lat: 18.558853, lng: -68.389922 },
        { lat: 18.558375, lng: -68.389729 },
        { lat: 18.558032, lng: -68.389182 },
        { lat: 18.558050, lng: -68.388613 },
        { lat: 18.558256, lng: -68.388213 },
        { lat: 18.558744, lng: -68.387929 },
      ]
    
      velocity = 5
      initialDate = new Date()
    
      getDistance = () => {
        // seconds between when the component loaded and now
        const differentInTime = (new Date() - this.initialDate) / 1000 // pass to seconds
        return differentInTime * this.velocity // d = v*t -- thanks Newton!
      }
    
      componentDidMount = () => {
        this.interval = window.setInterval(this.consoleDistance, 1000)
      }
    
      componentWillUnmount = () => {
        window.clearInterval(this.interval)
      }
    
      consoleDistance = () => {
        console.log(this.getDistance())
      }
    
      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)
      }
    
      render = () => {
        return (
          <GoogleMap
            defaultZoom={16}
            defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
            >
              <Polyline path={this.path} options={{ strokeColor: "#FF0000 "}} />
              <Marker position={this.path[this.path.length - 1]} />
          </GoogleMap>
        )
      }
    }
    
    const MapComponent = withScriptjs(withGoogleMap(Map))
    
    export default () => (
      <MapComponent
      googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
      loadingElement={<div style={{ height: `100%` }} />}
      containerElement={<div style={{ height: `400px`, width: '500px' }} />}
      mapElement={<div style={{ height: `100%` }} />}
      />
    )
    
    

    リアルタイムでトレイルのレンダリング


    今、我々はリアルタイムで車をレンダリングする必要があります.我々は直線の束を持っており、車は2つの中になります.それで、我々は若干の論理を我々の州に動かして、それを毎秒更新します.
    まず、追加しましょうprogress 我々の状態に、我々のpolylineとマーカーをその状態に続いてください.
      state = {
        progress: [],
      }
    
      render = () => {
        return (
          <GoogleMap
            defaultZoom={16}
            defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
            >
              { this.state.progress && (
                <>
                  <Polyline path={this.state.progress} options={{ strokeColor: "#FF0000 "}} />
                  <Marker position={this.state.progress[this.state.progress.length - 1]} />
                </>
              )}
          </GoogleMap>
        )
      }
    }
    
    今私たちは変更するかconsoleDistance to moveObject そして、すでに通過したパスの一部を抽出します.
      componentDidMount = () => {
        this.interval = window.setInterval(this.moveObject, 1000)
      }
    
      moveObject = () => {
        const distance = this.getDistance()
        if (! distance) {
          return
        }
        const progress = this.path.filter(coordinates => coordinates.distance < distance)
        this.setState({ progress })
      }
    
    すべてをまとめて置く
    あなたが気づいたように、私たちはすでに渡された線を追加しているので、車は“ジャンプ”、しかし、車はprogress その他のthis.path . だから、アニメーションをスムーズにするには、我々はこれらの2つの行内の進捗状況を知っているし、それらの2つの行内の座標を見つける必要があります.Googleは私たちにそれをする機能を提供しますgoogle.maps.geometry.spherical.interpolate .
    完成moveObject 関数は以下の通りです.
      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 })
      }
    
    そして今、それは滑らかに見える!
    結果は次のようになります.
    import React from 'react';
    import { withGoogleMap, withScriptjs, GoogleMap, Polyline, Marker } from 'react-google-maps'
    
    class Map extends React.Component {
      state = {
        progress: [],
      }
    
      path = [
        { lat: 18.558908, lng: -68.389916 },
        { lat: 18.558853, lng: -68.389922 },
        { lat: 18.558375, lng: -68.389729 },
        { lat: 18.558032, lng: -68.389182 },
        { lat: 18.558050, lng: -68.388613 },
        { lat: 18.558256, lng: -68.388213 },
        { lat: 18.558744, lng: -68.387929 },
      ]
    
      velocity = 5
      initialDate = new Date()
    
      getDistance = () => {
        // seconds between when the component loaded and now
        const differentInTime = (new Date() - this.initialDate) / 1000 // pass to seconds
        return differentInTime * this.velocity // d = v*t -- thanks Newton!
      }
    
      componentDidMount = () => {
        this.interval = window.setInterval(this.moveObject, 1000)
      }
    
      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)
      }
    
      render = () => {
        return (
          <GoogleMap
            defaultZoom={16}
            defaultCenter={{ lat: 18.559008, lng: -68.388881 }}
            >
              { this.state.progress && (
                <>
                  <Polyline path={this.state.progress} options={{ strokeColor: "#FF0000 "}} />
                  <Marker 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?v=3.exp&libraries=geometry,drawing,places"
      loadingElement={<div style={{ height: `100%` }} />}
      containerElement={<div style={{ height: `400px`, width: '500px' }} />}
      mapElement={<div style={{ height: `100%` }} />}
      />
    )
    
    
    今、我々はそれがさらに良く見えるように我々のパスと速度を変更する必要があります.これはルートとドライバによって変わるでしょう.
    より良いパス(this 100 km/hで、我々は以下を持ちます:
    パート2のために我々は車のアイコンをカスタマイズし、それが起こっている方向に直面するように!
    あなたが質問をするならば、私に知らせてください:D