Home > Mobile >  How to draw a Map using react-google-maps/api package?
How to draw a Map using react-google-maps/api package?

Time:01-17

I'm trying to build an app that has a Map and every time a user clicks the map, that action should leave a marker on that point, but if he clicks more than once, that should create a polyline between those coordinates and if he rights click a marker that he made, everything after that marker should be deleted. Well, I have problems with implementing adding those markers and the polyline, I am using @react-google-maps/api version ^2.17.1 and react ^18.2.0. I tried using useEffect on an array which holds coordinates added before using the onClick method in the component, but nothing shows up, that array didn't event change at all. I searched a lot on Youtube and Google to see if I get a tutorial for @react-google-maps/api that can help me with that, but no luck.

Here is my Map.jsx file:

import React from 'react'
import {GoogleMap, Marker, Polyline, useJsApiLoader} from '@react-google-maps/api'
import * as key from '../../constants/actions';
import { useEffect, useState } from 'react';



const Map = () => {

  let coordinates = [];
  const { isLoaded } = useJsApiLoader({
    id:'google-map-script',
    googleMapsApiKey: key.MAPS_API_KEY
  })

  const [map, setMap] = React.useState(null)
  const onl oad = React.useCallback(function callback(map) {
  const bounds = new window.google.maps.LatLngBounds(center);
    // map.fitBounds(bounds);
    setMap(map)
  }, [])

  const onUnmount = React.useCallback(function callback(map) {
    setMap(null)
  }, [])
  const containerStyle ={
    width:'100vw',
    height:'100vh',
    background:'green'
  }
    
  const center = {
    lat: 44.087585,
    lng: -39.899556
  }
    
  const onl oadMarker = marker => {
    console.log('marker: ', marker)
  }
  const onl oadPoly = polyline => {
    console.log('polyline: ', polyline)
  };
  const options = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35,
    clickable: false,
    draggable: false,
    editable: false,
    visible: true,
    radius: 30000,
    paths: coordinates,
    zIndex: 1
  };
  return isLoaded ? (
   <div style={{padding:'10px'}}>
    
    <GoogleMap mapContainerStyle={containerStyle}
     center={center}
     zoom={3}
    onl oad={onLoad}
    onUnmount={onUnmount}
    onClick={(e) => {
      coordinates.push({lat:e.latLng.lat(), lng: e.latLng.lng});
      <Marker position={{lat:e.latLng.lat(), lng: e.latLng.lng}} onl oad={onLoadMarker}/>;
      <Polyline path={coordinates} options={options} onl oad={onLoadPoly} />
    }}
    >
     
    </GoogleMap>
   </div>
  ) : <></>
 
}

export default Map

I'll appreciate any help. Thank you!

CodePudding user response:

I tried reproducing your code and made it work somehow. I noticed that you are trying to push the new markers into an array but that's not how it works in React. You need to utilize State Hooks and map method to be able to modify your array and update your Google Maps map whenever you click on it. Here's some references to read that might be helpful on your future endeavors:

Updating Arrays in State

Learn About Map in ReactJS

Now to how it was coded, here's the State hooks that you need:

  // Hook for center

  // This hook is used for updating 
  // the center whenever you click on the map
  const [center, setCenter] = React.useState({
    lat: 44.087585,
    lng: -39.899556
  });

  // Hook for polyline path

  // This is an array used for storing 
  // the sequence of your clicks which 
  // will be used later on when double clicking
  // the map to render the polyline.
  const [path, setPath] = React.useState([]);
  
  // This array is where the path sequence
  // will be stored once you
  // double click any marker. 
  const [loadPolyline, setLoadPolyline] = React.useState([]);

  // Hook for the location per click on the MAP
  
  // This is the where the location of your
  // click is stored which is the data used
  // for rendering your Marker, this is an
  // array and is updated each click.
  const [location, setLocation] = React.useState({
    markers: [
      {
        title: "The marker`s title will appear as a tooltip.",
        name: "",
        position: null
      }
    ]
  });

Then here's for the functions:

  // Function when clicking on the MAP

  // This is the function that updates
  // the location hook array that will
  // store new markers on click.
  const mapClicked = (e) => {
    const lat = e.latLng.lat();
    const lng = e.latLng.lng();
    const markerLoc = { lat: lat, lng: lng };
    const markerCoordinate = `lat: ${lat} lng: ${lng}`;
    setPath((previousState) => [...previousState, { lat: lat, lng: lng }]);
    setCenter({ lat: lat, lng: lng });
    setLocation((previousState) => {
      return {
        markers: [
          ...previousState.markers,
          {
            title: "",
            name: markerCoordinate,
            position: markerLoc
          }
        ]
      };
    });
  };

  // handle rightclick

  // This is a function that will reset
  // your locations, path, polyline arrays
  //  which will remove all
  // stored and rendered markers/polyline.
  const handleRightClick = () => {
    setLocation({
      markers: [
        {
          title: "The marker`s title will appear as a tooltip.",
          name: "",
          position: null
        }
      ]
    });
    setLoadPolyline([]);
    setPath([]);
  };

  //handle doubleclicks
  
  const handleDoubleClick = (e) => {
    setLoadPolyline(path);
  };

And here's how your <GoogleMap> component would look like:

  //Loads the MAP
  return isLoaded ? (
    <div style={{ padding: "10px" }}>
      <GoogleMap
        mapContainerStyle={containerStyle}
        center={center}
        zoom={3}
        onl oad={onLoad}
        onUnmount={onUnmount}
        onClick={mapClicked}
      >
        {<!--Here's the map method for your markers array-->}
        {location.markers.map((markers, key) => (
          <Marker
            icon={"https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png"}
            key={key}
            title={markers.title}
            name={markers.name}
            position={markers.position}
            onRightClick={handleRightClick}
            onDblClick={handleDoubleClick}
          >
          </Marker>
        ))}
        <Polyline path={loadPolyline} options={options} />
      </GoogleMap>
    </div>
  ) : (
    <></>
  );

Here's a proof of concept on codesanbox for you to try out.

P.S. The polyline seems to have an offset away from the marker and I've been banging my head on the wall for quite awhile trying to fix it.

But still, Hope this helps!

  • Related