routesleafletreact-leafletleaflet-routing-machine

how to draw a route by array of points using leaflet-routing-machine?


I want to drag route from many point using leaflet and leaflet-routing-machine. I do not know How to pass all of locations into the waypoints.

import { useEffect, useState } from "react";
import L from "leaflet";
import "leaflet-routing-machine/dist/leaflet-routing-machine.css";
import "leaflet-routing-machine";
import { useMap } from "react-leaflet";

L.Marker.prototype.options.icon = L.icon({
    iconUrl: "https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png"
});

export default function RoutingLayer({ route }) {
    const map = useMap();
    const waypoints = route ? route : null;
    const [routing, setRouting] = useState([]);

    useEffect(() => {
        var temp = get_route(waypoints)
        setRouting(temp);

        if (!map) return;
        const routingControl = L.Routing.control({
            waypoints: routing.length > 0 && routing,
            // waypoints: [L.latLng(37.2461188, 49.6219894), L.latLng(35.7074147, 51.3376843)],
            routeWhileDragging: true
        }).addTo(map);

        return () => map.removeControl(routingControl);
    }, [map, waypoints]);

    async function get_route(waypoints) {
        let temp = []
        for (let i = 0; i < waypoints.length; i++) {
            temp.push(L.latLng(waypoints[i][0], waypoints[i][1]))
        }
        return temp;
    }

    return null;
}

Above code works with waypoints: [L.latLng(37.2461188, 49.6219894), L.latLng(35.7074147, 51.3376843)], But I want to make dynamic this points. This code has not error but does not drag route. Because waypoints is empty.

I guess to use async await for get_route but does not work.

This is MapContainer:

import React, { useEffect, useState } from 'react'
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import "./monitoring.css";
import RoutingLayer from "./RoutingLayer";

function Map() {
    const [allLocations, setAllLocations] = useState([])
    const [allDetails, setAllDetails] = useState([])
    const [route, setRoute] = useState([])

    useEffect(() => {
        GetAllBusLocation().then((res) => {
            const data = res.data.data;
            var points = []
            setAllDetails(data);
            for (let i = 0; i < data.length; i++) {
                points.push(data[i].spanData.coordinates)
            }
            data.map((bus) => {
                points.push(bus.spanData.coordinates)
            })
            setAllLocations(points)
            map_route(points);
        })
    }, [])

    const map_route = (waypoints) => {
        let route = []
        for (let i = 0; i < waypoints.length; i++) {
            let temp = []
            temp.push(waypoints[i][0], waypoints[i][1])
            route.push(temp)
        }
        setRoute(route);
        return route;
    }

    return (
        <div style={{ width: "100%", height: "100%" }}>
            <MapContainer center={[32.4279, 53.6880]} zoom={7} scrolWheelZoom={true}>
                <TileLayer
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                <RoutingLayer route={route ? route : null} />
            </MapContainer>
        </div>
    )
}

export default Map

Solution

  • Finally, I solved this problem. It was an asynchrony issue. First, load points or locations and then convert to route and then draw route. So, I stopped running the rest until complete execution of get_route(points) using await.

    import L from "leaflet";
    
    function Map() {
    
        const [waypoints, setWaypoints] = useState([])
    
        useEffect(() => {
            GetAllBusLocation(user).then(async (res) => {
                ...
                // points is my coordinates
                var route = await get_route(points);
                setWaypoints(route);
            })
        }, [])
    
        async function get_route(waypoints) {
            let temp = []
            for (let i = 0; i < waypoints?.length; i++) {
                temp.push(L.latLng(waypoints[i][0], waypoints[i][1]))
            }
            return temp;
        }
    
    return (
            <MapContainer>
            ...
                 <RoutingBusLayer waypoints={waypoints ? waypoints : null} />
            </MapContainer>            
        )
    }
    
    export default Map