如何用Leaflet-Routing-Machine通过点数组绘制可拖拽动态路线?
Leaflet + leaflet-routing-machine 动态多点可拖拽路线问题修复
问题核心
使用静态坐标数组时路线正常可拖拽,但动态传入后端返回的坐标点后,waypoints为空导致路线无法生成且不可拖拽。
问题分析
- 异步函数误用:
get_route是async函数,直接赋值会返回Promise而非转换后的坐标数组,且useEffect中同步调用setRouting后,state更新是异步的,创建routingControl时routing仍为空数组。 - 坐标点重复添加:Map组件中同时用for循环和map方法向points数组push坐标,导致点位重复。
- 依赖state传递waypoints冗余:无需将转换后的坐标存入state,可直接在创建routingControl时同步转换,避免异步更新延迟。
修复方案
- 移除不必要的async函数,直接在useEffect中同步转换传入的route坐标为
L.latLng实例数组。 - 修复Map组件中重复添加坐标的逻辑,保留一种循环方式即可。
- 直接使用转换后的坐标数组初始化routingControl,无需依赖组件state。
修改后的代码
RoutingLayer组件
import { useEffect } 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(); useEffect(() => { if (!map || !route || route.length === 0) return; // 同步转换坐标为L.latLng实例 const waypoints = route.map(point => L.latLng(point[0], point[1])); const routingControl = L.Routing.control({ waypoints: waypoints, routeWhileDragging: true }).addTo(map); return () => map.removeControl(routingControl); }, [map, route]); return null; }
Map组件
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; const points = data.map(bus => bus.spanData.coordinates); setAllDetails(data); setAllLocations(points); map_route(points); }) }, []) const map_route = (waypoints) => { // 直接转换格式,无需额外循环嵌套 const route = waypoints.map(coords => [coords[0], coords[1]]); setRoute(route); } return ( <div style={{ width: "100%", height: "100%" }}> <MapContainer center={[32.4279, 53.6880]} zoom={7} scrollWheelZoom={true}> <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <RoutingLayer route={route} /> </MapContainer> </div> ) } export default Map
内容的提问来源于stack exchange,提问作者ParisaN
相关产品推荐
相关产品推荐

