Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How i draw a route with react-google-maps component?

I'm traying to draw a route between two points with react-google-maps but is not working for me. Can u help me with this problem? Here's a example of my react component.

import React from 'react';
import {
  withScriptjs,
  withGoogleMap,
  GoogleMap,
  Marker,
} from 'react-google-maps';
import MapDirectionsRenderer from './app_map_directions_render';

const Map = withScriptjs(
  withGoogleMap(props => (
    <GoogleMap
      defaultCenter={props.defaultCenter}
      defaultZoom={props.defaultZoom}
    >
      {props.places.map((marker, index) => {
        const position = {lat: marker.latitude, lng: marker.longitude};
        return <Marker key={index} position={position}/>;
      })}
      <MapDirectionsRenderer places={props.places} travelMode={window.google.maps.TravelMode.DRIVING} />
    </GoogleMap>
  ))
);

const AppMap = props => {
  const {places} = props;

  const {
    loadingElement,
    containerElement,
    mapElement,
    defaultCenter,
    defaultZoom
  } = props;

  return (
    <Map
      googleMapURL={
        'https://maps.googleapis.com/maps/api/js?key=' +
        googleMapsApiKey +
        '&v=3.exp&libraries=geometry,drawing,places'
      }
      places={places}
      loadingElement={loadingElement || <div style={{height: `100%`}}/>}
      containerElement={containerElement || <div style={{height: "80vh"}}/>}
      mapElement={mapElement || <div style={{height: `100%`}}/>}
      defaultCenter={defaultCenter || {lat: 25.798939, lng: -80.291409}}
      defaultZoom={defaultZoom || 11}
    />
  );
};

export default AppMap;

And my MapDirectionsRenderer Component

import React, {Component} from 'react';
import { DirectionsRenderer } from "react-google-maps";

export default class MapDirectionsRenderer extends Component {
  state = {
    directions: null,
    error: null
  };

  componentDidMount() {
    const { places, travelMode } = this.props;

    const waypoints = places.map(p =>({
        location: {lat: p.latitude, lng: p.longitude},
        stopover: true
    }))
    if(waypoints.length >= 2){
    const origin = waypoints.shift().location;
    const destination = waypoints.pop().location;

    const directionsService = new window.google.maps.DirectionsService();
    directionsService.route(
      {
        origin: origin,
        destination: destination,
        travelMode: travelMode,
        waypoints: waypoints
      },
      (result, status) => {
        if (status === window.google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result
          });
        } else {
          this.setState({ error: result });
        }
      }
    );
    }
  }

  render() {
    if (this.state.error) {
      return <h1>{this.state.error}</h1>;
    }
    return <DirectionsRenderer directions={this.state.directions} />;
  }
}
like image 470
Raul Castro Rivero Avatar asked Mar 29 '19 20:03

Raul Castro Rivero


People also ask

How does Google Maps generate a route?

Google scores the possible roads taking into account factors like real-time traffic conditions, the distance of the route, to find the quickest way. Finally, Google Maps will provide the shortest route and give some alternatives varying on distance or time taken.


1 Answers

To render a route Google Maps API provides Directions Service, in case of react-google-maps library DirectionsRenderer component is available which is a wrapper around DirectionsRenderer class which in turn:

Renders directions obtained from the DirectionsService.

Assuming the data for route is provided in the following format:

const places = [
  {latitude: 25.8103146,longitude: -80.1751609},
  {latitude: 27.9947147,longitude: -82.5943645},
  {latitude: 28.4813018,longitude: -81.4387899},
  //...
]

the following component could be introduced to calculate and render directions via react-google-maps library:

class MapDirectionsRenderer extends React.Component {
  state = {
    directions: null,
    error: null
  };

  componentDidMount() {
    const { places, travelMode } = this.props;

    const waypoints = places.map(p =>({
        location: {lat: p.latitude, lng:p.longitude},
        stopover: true
    }))
    const origin = waypoints.shift().location;
    const destination = waypoints.pop().location;



    const directionsService = new google.maps.DirectionsService();
    directionsService.route(
      {
        origin: origin,
        destination: destination,
        travelMode: travelMode,
        waypoints: waypoints
      },
      (result, status) => {
        if (status === google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result
          });
        } else {
          this.setState({ error: result });
        }
      }
    );
  }

  render() {
    if (this.state.error) {
      return <h1>{this.state.error}</h1>;
    }
    return <DirectionsRenderer directions={this.state.directions} />;
  }
}

Here is a demo


For React 16.8 or above, MapDirectionsRenderer could be implemented (using Hooks) as below:

function MapDirectionsRenderer(props) {
  const [directions, setDirections] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const { places, travelMode } = props;

    const waypoints = places.map(p => ({
      location: { lat: p.latitude, lng: p.longitude },
      stopover: true
    }));
    const origin = waypoints.shift().location;
    const destination = waypoints.pop().location;

    const directionsService = new google.maps.DirectionsService();
    directionsService.route(
      {
        origin: origin,
        destination: destination,
        travelMode: travelMode,
        waypoints: waypoints
      },
      (result, status) => {
        console.log(result)
        if (status === google.maps.DirectionsStatus.OK) {
          setDirections(result);
        } else {
          setError(result);
        }
      }
    );
  });

  if (error) {
    return <h1>{error}</h1>;
  }
  return (
    directions && (
      <DirectionsRenderer directions={directions} />
    )
  );
}
like image 124
Vadim Gremyachev Avatar answered Oct 12 '22 12:10

Vadim Gremyachev