使用@react-google-maps/api的PolylineF首次加载地图时绘制异常
问题解决:首次加载时PolylineF出现两条折线
问题重现
使用@react-google-maps/api的PolylineF结合google.maps.DirectionsService绘制步行路径时,首次加载后第一次绘制会出现两条线:一条是预期的步行路径,另一条是两点间的直线;后续操作则正常。
问题原因
- 异步更新导致中间渲染:原代码中每次循环都调用
setPoints更新状态,每次更新都会触发PolylineF重新渲染,可能在路径计算完成前出现临时异常渲染。 - 依赖缺失:
useEffect未监听dirService的变化,导致dirService初始化完成后,无法自动重新执行路径计算。 - 未判断服务可用性:在
dirService未初始化完成时就执行drawPolygon,可能导致points状态未被正确更新,触发异常渲染。
修复方案
1. 一次性收集路径点再更新状态
避免多次触发状态更新,先把所有路径点收集完成后再一次性设置points:
const drawPolygon = async (markpoints) => { if (!dirService) return; // 服务未就绪时直接返回 let allPoints = []; for (let i = 0; i < markpoints.length - 1; i++) { try { const result = await dirService.route({ origin: markpoints[i], destination: markpoints[i + 1], travelMode: window.google.maps.TravelMode.WALKING }); const newPoints = result.routes[0].overview_path.map(p => ({ lat: p.lat(), lng: p.lng() })); allPoints.push(...newPoints); } catch (error) { console.log(error.message); } } setPoints(allPoints); // 一次性更新所有路径点 }
2. 补全useEffect依赖项
将dirService加入useEffect的依赖数组,确保服务初始化完成后自动重新计算路径:
useEffect(() => { // 确保有至少两个点且服务就绪时才执行绘制 if (markpoints.length > 1 && dirService) { drawPolygon(markpoints); } }, [markpoints, dirService]) // 添加dirService到依赖
3. 控制PolylineF的渲染时机(可选)
添加状态控制折线的渲染,避免在路径计算过程中显示异常内容:
const [isDrawingComplete, setIsDrawingComplete] = useState(false); const drawPolygon = async (markpoints) => { if (!dirService) return; setIsDrawingComplete(false); let allPoints = []; for (let i = 0; i < markpoints.length - 1; i++) { try { const result = await dirService.route({ origin: markpoints[i], destination: markpoints[i + 1], travelMode: window.google.maps.TravelMode.WALKING }); const newPoints = result.routes[0].overview_path.map(p => ({ lat: p.lat(), lng: p.lng() })); allPoints.push(...newPoints); } catch (error) { console.log(error.message); } } setPoints(allPoints); setIsDrawingComplete(true); } // 渲染时只在绘制完成后显示折线 {isDrawingComplete && <PolylineF path={points} geodesic={true} options={{ fillColor: "red", strokeColor: "#ff2527", strokeOpacity: 0.75, strokeWeight: 2, }} />}
完整修复后代码
const PolygonOnMap = ({ markpoints, close, remove, getPoints, readOnly, ss }) => { const { isLoaded } = useContext(GoogleMapAPIContext) const [points, setPoints] = useState([]) const [isDrawingComplete, setIsDrawingComplete] = useState(false) const dirService = useMemo(()=>{ console.log('useMemo',isLoaded); if(isLoaded) return new window.google.maps.DirectionsService(); return null; },[isLoaded]) const drawPolygon = async (markpoints) => { if (!dirService) return; setIsDrawingComplete(false); let allPoints = []; for (let i = 0; i < markpoints.length - 1; i++) { try { const result = await dirService.route({ origin: markpoints[i], destination: markpoints[i + 1], travelMode: window.google.maps.TravelMode.WALKING }); const newPoints = result.routes[0].overview_path.map(p => ({ lat: p.lat(), lng: p.lng() })); allPoints.push(...newPoints); } catch (error) { console.log(error.message); } } setPoints(allPoints); setIsDrawingComplete(true); } useEffect(() => { if (markpoints.length > 1 && dirService) { drawPolygon(markpoints); } }, [markpoints, dirService]) return ( <div> {markpoints.map((p, i) => <MarkerF key={i} position={p} index={i} />)} {isDrawingComplete && <PolylineF path={points} geodesic={true} options={{ fillColor: "red", strokeColor: "#ff2527", strokeOpacity: 0.75, strokeWeight: 2, }} />} </div> ) } export default PolygonOnMap
内容的提问来源于stack exchange,提问作者Alis
相关产品推荐
相关产品推荐

