概述
本文在mapboxGL框架下,分享一种基于高德Web API实现沿路画面的实现。
实现效果
实现
1. 实现思路
- 通过点击获取路径的起点和终点;
- 将多次规划路径的结果连成一条线;
- 当鼠标点击回到第一个点的时候结束绘制;
- 绘制结束后将路径闭合,形成多边形,并对形成的多边形进行处理;
实现代码
<template><div class="map"><lzugismap-map:onLoad="mapLoaded":maxPitch="0":minPitch="0":pitch="0":style="style":center="[113.91505797606129, 22.536719264512044]":zoom="zoom":interactive="true"></lzugismap-map><div class="map-tools"><button :disabled="isDraw" @click="startDraw">绘制</button></div></div>
</template><script>
import { LzugismapMap } from "@lzugismap/vue-lzugismap";
import * as turf from "@turf/turf";class Geojson {constructor(features = []) {this.features = features;this.type = "FeatureCollection";}
}let points = [],routes = [];export default {components: {LzugismapMap,},data() {return {map: null,zoom: 16,isDraw: false,};},methods: {mapLoaded(map) {this.map = map;map.addSource("route-source", {type: "geojson",data: new Geojson(),});map.addSource("fill-source", {type: "geojson",data: new Geojson(),});map.addSource("point-source", {type: "geojson",data: new Geojson(),});map.addLayer({id: "route-source-fill",source: "fill-source",type: "fill",paint: {"fill-color": "red","fill-opacity": 0.15,},});map.addLayer({id: "route-source-line",source: "route-source",type: "line",paint: {"line-color": "red","line-width": 3.5,},});map.addLayer({id: "route-point",source: "point-source",type: "circle",paint: {"circle-color": "blue","circle-opacity": 0.8,"circle-radius": 5,},});// this.showRoute();},startDraw() {this.isDraw = true;points = [];routes = [];const that = this;that.map.getSource("point-source").setData(new Geojson());that.map.getSource("route-source").setData(new Geojson());that.map.getSource("fill-source").setData(new Geojson());that.map.getCanvas().style.cursor = "crosshair";const mapClickEvt = (e) => {const point = e.lngLat.toArray();points.push(point);that.map.getSource("point-source").setData(new Geojson(points.map((p) => turf.point(p))));if (points.length > 1) {const p0 = points[0];const start = points[points.length - 2];let end = points[points.length - 1];const dis = turf.distance(turf.point(p0), turf.point(end)) * 1000;const isEnd = dis < 10;if (isEnd) {end = p0;}// driving walkingconst url = `https://restapi.amap.com/v3/direction/walking?origin=${start.join(",")}&destination=${end.join(",")}&output=JSON&key={你申请的key}`;fetch(url).then((res) => res.json()).then((res) => {const paths = res?.route?.paths || [];paths.forEach(({ steps }) => {steps.forEach(({ polyline }) => {const _points = polyline.split(";").map((item) => item.split(",").map(Number));routes = [...routes, ..._points];});});if (isEnd) {const polygon = turf.lineToPolygon(turf.lineString(routes));const geojson = turf.polygonSmooth(polygon, { iterations: 10 });that.map.getSource("route-source").setData(geojson);that.map.getSource("fill-source").setData(geojson);that.isDraw = false;this.map.off("click", mapClickEvt);that.map.getCanvas().style.cursor = "";} else {const line = turf.lineString(routes);that.map.getSource("route-source").setData(line);}});}};this.map.on("click", mapClickEvt);},},
};
</script><style scoped lang="scss">
.map {width: 100%;height: 100%;
}
.map-tools {position: absolute;right: 2rem;top: 2rem;z-index: 99;
}
</style>