一种基于高德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>
相关推荐
Cc.Y4 小时前
Java零基础入门:字符串深度掌握——从基础API到StringBuilder性能优化
java·开发语言·性能优化
java资料站8 小时前
十一、评估测试
开发语言·人工智能·python
左手の明天9 小时前
SLIP 协议封装与解析详解:原理、C 代码与实战案例
linux·c语言·开发语言·c++
扶风ff9 小时前
新品知识更新太快?用练题簿在线刷题,安排企业培训的小测与复盘
前端·学习·小程序
海上小飞龙9 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
对空六课9 小时前
支持注意力分析的热力图工具有哪些?
前端·数据库·数据分析
朝朝辞暮i9 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
狗凯之家源码网9 小时前
淘客口令落地页生成器 PHP 版深度评测
开发语言·php
画绛集美术9 小时前
本地化部署LLM用于美术史问答:一间美术教室的实践记录
开发语言·php
八解毒剂10 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理