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.
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;
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;