Search code examples
javascriptreactjsgoogle-mapsecmascript-6react-google-maps

How to set start point in react-google-maps


I am working on an application I am usingreact-google-maps where I've integrated multiple stop functionality in my application. Now I want to set its starting point like, For example, I want to draw multiple stops from its starting point and it must be a marker with text (Start). I really tried but didn't able to resolve this solution, I will also attach an image of what I want to achieve.

image preview

Code

import React, { useState } from "react";
import {
  GoogleMap,
  InfoWindow,
  Marker,
  Polyline,
} from "@react-google-maps/api";

function Map({ scheduledOrders }) {
  const [activeMarker, setActiveMarker] = useState(null);

  let markers =
    scheduledOrders !== undefined &&
    scheduledOrders &&
    scheduledOrders[0] &&
    scheduledOrders[0].map((item, index) => ({
      id: index + 1,
      name: item.customerName + " - " + item.customerAddress,
      position: {
        lat: Number(item && item.order_lat, 10),
        lng: Number(item && item.order_lng, 10),
      },
    }));


  console.log("@@@markser", markers);

  const handleActiveMarker = (marker) => {
    if (marker === activeMarker) {
      return;
    }
    setActiveMarker(marker);
  };

  const handleOnLoad = (map) => {
    const bounds = new window.google.maps.LatLngBounds();
    markers && markers.forEach(({ position }) => bounds.extend(position));
    map.fitBounds(bounds);
  };

  return (
    <GoogleMap
      onLoad={handleOnLoad}
      onClick={() => setActiveMarker(null)}
      mapContainerStyle={{ width: "100%", height: "88vh" }}
    >
      <Polyline
        path={
          scheduledOrders !== undefined &&
          scheduledOrders &&
          scheduledOrders[0] &&
          scheduledOrders[0].map((item) => ({
            lat: Number(item && item.order_lat, 10),
            lng: Number(item && item.order_lng, 10),
          }))
        }
        options={{
          strokeColor: "#07966B",
          strokeOpacity: 1,
          strokeWeight: 2,
          icons: [
            {
              icon: "hello",
              offset: "0",
              repeat: "10px",
            },
          ],
        }}
      />
      {markers &&
        markers.map(({ id, name, position }) => (
          <Marker
            key={id}
            position={position}
            onClick={() => handleActiveMarker(id)}
            label={{ text: `${id}`, color: "white" }}
          >
            {activeMarker === id ? (
              <InfoWindow onCloseClick={() => setActiveMarker(null)}>
                <div>{name}</div>
              </InfoWindow>
            ) : null}
          </Marker>
        ))}
    </GoogleMap>
  );
}

export default Map;

Solution

  • Your code appears to have the same coordinates for the start and end path of the polyline. To achieve your use case, I got 2 ways to solve this.

    Here's the first, you need to first get the coordinates of your starting point and put it in a separate variable.Then you need to create a separate <Marker> object for this coordinate with the condition that it will check if the start coordinate variable has value. This will create a separate Marker object that you can customize. Next you only need to map all the middle(waypoint) coordinates in your markers variable.

    Here's a sample code and a code snippet that I made. I just passed the scheduledOrders value from json file.

    import React, { useState } from "react";
    import {
      GoogleMap,
      InfoWindow,
      Marker,
      Polyline
    } from "@react-google-maps/api";
    
    import scheduledOrders from "./data.json";
    
    function Map() {
      const [activeMarker, setActiveMarker] = useState(null);
      let startMarker = null;
      let wayptMarker = [];
    
    //get the first point and put it in a startMarker variable then put the middle points in an array(wayptMarker)
      scheduledOrders.map((item, index, arr) => {
        if (index == 0 || index == arr.length - 1) {
          //Since the start and end point are the same, I only get the start point details in my startMarker variable
          if (index == 0) {
            startMarker = item;
          }
        } else {
          wayptMarker.push(item);
        }
      });
    
    //put your startposition here
      let startPosition = {
        lat: startMarker.order_lat,
        lng: startMarker.order_lng
      };
    //put your start name here
      let startName =
        startMarker.customerName + " - " + startMarker.customerAddress;
    
    
      let markers =
        scheduledOrders !== undefined &&
        scheduledOrders &&
        wayptMarker.map((item, index) => ({
          id: index + 1,
          name: item.customerName + " - " + item.customerAddress,
          position: {
            lat: Number(item && item.order_lat, 10),
            lng: Number(item && item.order_lng, 10)
          }
        }));
    
    
      console.log("@@@markser", scheduledOrders);
    
      const handleActiveMarker = marker => {
        if (marker === activeMarker) {
          return;
        }
        setActiveMarker(marker);
      };
    
      const handleOnLoad = map => {
        const bounds = new window.google.maps.LatLngBounds();
        markers && markers.forEach(({ position }) => bounds.extend(position));
        map.fitBounds(bounds);
      };
    
      return (
        <GoogleMap
          onLoad={handleOnLoad}
          onClick={() => setActiveMarker(null)}
          mapContainerStyle={{ width: "100%", height: "88vh" }}
        >
          <Polyline
            path={
              scheduledOrders !== undefined &&
              scheduledOrders &&
              scheduledOrders[0] &&
              scheduledOrders.map(item => ({
                lat: Number(item && item.order_lat, 10),
                lng: Number(item && item.order_lng, 10)
              }))
            }
            options={{
              strokeColor: "#07966B",
              strokeOpacity: 1,
              strokeWeight: 2,
              icons: [
                {
                  icon: "hello",
                  offset: "0",
                  repeat: "10px"
                }
              ]
            }}
          />
         {/* I created a marker solely for startMArker where you can customize the  icon for this only marker */}
          {startMarker != null && (
            <Marker
              key="start"
              position={startPosition}
              onClick={() => handleActiveMarker("start")}
              label={{ text: `START`, color: "black" }}
              icon="http://maps.google.com/mapfiles/kml/shapes/arrow.png"
            >
              {activeMarker === "start" ? (
                <InfoWindow onCloseClick={() => setActiveMarker(null)}>
                  <div>{startName}</div>
                </InfoWindow>
              ) : null}
            </Marker>
          )}
      {/* The following Marker object will only create markers for the middle points */}
          {markers &&
            markers.map(({ id, name, position }) => (
              <Marker
                key={id}
                position={position}
                onClick={() => handleActiveMarker(id)}
                label={{ text: `${id}`, color: "white" }}
              >
                {activeMarker === id ? (
                  <InfoWindow onCloseClick={() => setActiveMarker(null)}>
                    <div>{name}</div>
                  </InfoWindow>
                ) : null}
              </Marker>
            ))}
        </GoogleMap>
      );
    }
    
    export default Map;
    

    The second way is to simply just put the condition in your <Marker> object that will check if the markers that you are mapping is the first or the last then it will show a<Marker> object for the start and if not, a different <Marker> object that will show your waypoints.

    Here's the sample code and code snippet below:

    import React, { useState } from "react";
    import {
      GoogleMap,
      InfoWindow,
      Marker,
      Polyline
    } from "@react-google-maps/api";
    
    import scheduledOrders from "./data.json";
    
    function Map() {
      const [activeMarker, setActiveMarker] = useState(null);
    
      let markers =
        scheduledOrders !== undefined &&
        scheduledOrders &&
        scheduledOrders.map((item, index) => ({
          id: index + 1,
          name: item.customerName + " - " + item.customerAddress,
          position: {
            lat: Number(item && item.order_lat, 10),
            lng: Number(item && item.order_lng, 10)
          }
        }));
    
      console.log("@@@markser", scheduledOrders);
    
      const handleActiveMarker = marker => {
        if (marker === activeMarker) {
          return;
        }
        setActiveMarker(marker);
      };
    
      const handleOnLoad = map => {
        const bounds = new window.google.maps.LatLngBounds();
        markers && markers.forEach(({ position }) => bounds.extend(position));
        map.fitBounds(bounds);
      };
    
      return (
        <GoogleMap
          onLoad={handleOnLoad}
          onClick={() => setActiveMarker(null)}
          mapContainerStyle={{ width: "100%", height: "88vh" }}
        >
          <Polyline
            path={
              scheduledOrders !== undefined &&
              scheduledOrders &&
              scheduledOrders[0] &&
              scheduledOrders.map(item => ({
                lat: Number(item && item.order_lat, 10),
                lng: Number(item && item.order_lng, 10)
              }))
            }
            options={{
              strokeColor: "#07966B",
              strokeOpacity: 1,
              strokeWeight: 2,
              icons: [
                {
                  icon: "hello",
                  offset: "0",
                  repeat: "10px"
                }
              ]
            }}
          />
    
          {/* The following Marker object will check if the index is the start or end */}
          {markers &&
            markers.map(({ id, name, position }, i, arr) => {
              if (i == 0 || i == arr.length)
                return (
                  <Marker
                    key="start"
                    position={position}
                    onClick={() => handleActiveMarker("start")}
                    label={{ text: `START`, color: "black" }}
                    icon="http://maps.google.com/mapfiles/kml/shapes/arrow.png"
                  >
                    {activeMarker === "start" ? (
                      <InfoWindow onCloseClick={() => setActiveMarker(null)}>
                        <div>This is the start</div>
                      </InfoWindow>
                    ) : null}
                  </Marker>
                );
              return (
                <Marker
                  key={id}
                  position={position}
                  onClick={() => handleActiveMarker(id)}
                  label={{ text: `${id - 1}`, color: "white" }}
                >
                  {activeMarker === id ? (
                    <InfoWindow onCloseClick={() => setActiveMarker(null)}>
                      <div>{name}</div>
                    </InfoWindow>
                  ) : null}
                </Marker>
              );
            })}
        </GoogleMap>
      );
    }
    
    export default Map;