一种基于高德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>
相关推荐
IT_陈寒5 分钟前
Vite的静态资源打包让我熬夜到三点,这坑千万别跳
前端·人工智能·后端
山河木马1 小时前
矩阵专题0-webGL中的矩阵
javascript·webgl·计算机图形学
徐小夕1 小时前
万字拆解 JitWord:企业级实时协同文档底层架构 + 大模型 AI 融合完整实践
前端·vue.js·github
一份执念1 小时前
uni-app 小程序分包限制处理与主包体积优化实战
前端·微信小程序
Asize1 小时前
多模态生图:从 Vite 工程化到前端调用 Qwen Image
javascript·人工智能·后端
MariaH1 小时前
初识MySQL
前端
陳陈陳2 小时前
从Token到Embedding:一篇文章搞懂大模型的「文字数学变形记」
前端·javascript·ai编程
十有八七2 小时前
AI时代的置身X内
前端·人工智能
用户938515635072 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
橘子星2 小时前
LLM 无状态架构实践:从原理到代码落地
前端·javascript·人工智能