一种基于高德Web API实现沿路画面的实现

概述

本文在mapboxGL框架下,分享一种基于高德Web API实现沿路画面的实现。

实现效果

实现

1. 实现思路

  1. 通过点击获取路径的起点和终点;
  2. 将多次规划路径的结果连成一条线;
  3. 当鼠标点击回到第一个点的时候结束绘制;
  4. 绘制结束后将路径闭合,形成多边形,并对形成的多边形进行处理;

实现代码

vue 复制代码
<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 walking
          const 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>
相关推荐
鸽鸽程序猿9 分钟前
【C语言】分支(选择)和循环语句
c语言·开发语言·学习·程序人生·学习方法·visual studio
交换喜悲12 分钟前
目标检测常用涨点方法:注意力机制小结(空间注意力、通道注意力、CBAM等)
开发语言·人工智能·深度学习·目标检测·计算机视觉·maven
编码时空的诗意行者13 分钟前
C++实现简化 QtBase(5):通过IEventLoopHost扩展实现win32消息循环
开发语言·c++·qt·信号槽
爪洼炒饭21 分钟前
java项目中与金额有关的计算注意事项
java·开发语言·spring boot·postgresql
fengzhuzhigu24 分钟前
Go源码--channel源码解读
开发语言·后端·golang
IT_Beijing_BIT25 分钟前
C++ 的常见算法 之一
开发语言·c++·算法
野槐28 分钟前
CSS原子化
前端·css
#学习的路上36 分钟前
Bean的管理
java·前端·数据库
香蕉麻花皮39 分钟前
vue3 滚动条滑动到元素位置时,元素加载
前端·javascript·vue.js
Coisinilove40 分钟前
MATLAB——循环语句
开发语言·算法·matlab