Vue3 + 高德地图实现围栏绘制与线路渲染(含 GeoJSON 支持)

在项目中,往往需要通过地图进行区域围栏绘制、线路渲染 等功能,用于数据可视化、行为监控、地理标注等业务场景。本文将基于 Vue 3 + 高德地图 JSAPI 实现一个完整的地图功能模块,包括:

  • 地图初始化与 GeoJSON 加载

  • 绘制围栏(可编辑)

  • 渲染多边形遮罩层

  • 动态加载中心线、左/右边界线等结构化线路

📌 适用于城市交通可视化、车辆轨迹管控、地图交互平台等项目。


🧩一、技术栈与依赖

  • Vue 3 Composition API

  • 高德地图 JSAPI v2.0

  • 支持 Element Plus 按钮交互(仅 UI)

  • 加载本地 GeoJSON 线路数据


🗺️二、地图初始化与基础设置

我们首先使用 @amap/amap-jsapi-loader 来加载高德地图 JS:

复制代码
AMapLoader.load({
  key: "你的高德Key",
  version: "2.0",
  plugins: [
    "AMap.MouseTool", "AMap.Polygon", "AMap.PolyEditor", 
    "AMap.OverlayGroup", "AMap.DistrictSearch", ...
  ],
}).then((AMap) => {
  map = new AMap.Map("container", {
    zoom: 15.5,
    center: [113.50099365, 23.04139783],
    mapStyle: "amap://styles/darkblue", // 暗色背景,突出图层
    WebGLParams: { preserveDrawingBuffer: true },
  });

  pointsGroup = new AMap.OverlayGroup();
  map.add(pointsGroup);

  drawGeoJsonLines(); // 加载线路
  drawDist(map);      // 加载遮罩层
});

🧱三、GeoJSON 数据线路渲染

使用一个本地 outlines.json 文件进行数据加载。我们通过 drawGeoJsonFeature 方法解析每一个 feature:

复制代码
const drawGeoJsonFeature = (feature) => {
  const { geometry, properties } = feature;

  // 多边形区域显示为透明遮罩
  const polygon = new AMap.Polygon({
    path: geometry.coordinates?.[0]?.map(([lng, lat]) => [lng, lat]),
    strokeColor: "#fff",
    strokeOpacity: 0.1,
    fillOpacity: 0.01,
  });
  polygon.setMap(map);
  overlays.push(polygon);

  // 渲染每一类线(如中心线、左右边界线)
  Object.entries(lineStyleMap).forEach(([key, color]) => {
    const lineData = properties[key];
    if (!lineData?.geometry?.length) return;

    const path = lineData.geometry.map(p => [p.lng, p.lat]);
    const polyline = new AMap.Polyline({ path, strokeColor: color });
    polyline.setMap(map);
    overlays.push(polyline);
  });
};

centerLineleftBoundaryLinerightBoundaryLine 等结构都封装在 GeoJSON 的 properties 属性中,便于扩展。


🖌️四、围栏绘制与编辑功能

地图点击按钮可开启手绘模式,利用高德的 MouseTool 工具类进行绘制:

复制代码
const drawFence = () => {
  let mouseTool = new AMap.MouseTool(map);
  mouseTool.polygon({
    strokeColor: "#FEB80A",
    strokeWeight: 6,
    fillOpacity: 0.2,
  });

  mouseTool.on("draw", (event) => {
    mouseTool.close(true);
    const path = event.obj.getPath().map((p) => [p.lng, p.lat]);
    blockDrawFence({ path, flag: "2" });
  });
};

用户绘制完成后,可进入编辑模式,并监听结束编辑事件:

复制代码
blockEditor = new AMap.PolyEditor(map, polygonLayer);
blockEditor.on("end", (event) => {
  emit("fence-update", event.target._opts.path); // 实时更新路径
});

🧱五、遮罩层区域绘制

为确保围栏和线路都只在我们指定的区域显示,我们绘制一个包含全国的"外包围"大矩形作为遮罩外框:

复制代码
const drawDist = (map) => {
  let outer = [
    new AMap.LngLat(-360, 90), new AMap.LngLat(-360, -90),
    new AMap.LngLat(360, -90), new AMap.LngLat(360, 90),
  ];
  let pathArray = [outer, JSON.parse(props.fences)];

  let polygon = new AMap.Polygon({
    strokeColor: "#00eeff",
    fillColor: "#71B3ff",
    fillOpacity: 0.5,
  });

  polygon.setPath(pathArray);
  map.add(polygon);
};

📌 注意:遮罩图层要最晚渲染,并使用较高的 fillOpacity,可防止路线图层"盖住"遮罩图层。


🎮六、交互 UI 与地图控制面板

复制代码
<el-button v-if="editPoints[0] == ''" @click="drawFence">标记角点</el-button>
<el-button v-else @click="editBlockDrawFence">编辑围栏</el-button>
<el-button v-else @click="editBlockCloseDrawFence">结束编辑</el-button>

可通过按钮实现"开始绘制 - 编辑围栏 - 结束编辑"三段式操作,符合用户思维流。


🧠七、层级问题及修复建议

问题:线路在遮罩层上方

此问题常见于:

  • 多边形 Polygon 图层未设置 zIndex,默认图层排序不一致;

  • 线路渲染顺序早于遮罩层;

  • 遮罩层 fillOpacity 太小。

✅解决方案:

复制代码
const polygon = new AMap.Polygon({
  path: coords,
  strokeColor: "#fff",
  fillColor: "#fff",
  fillOpacity: 0.9,  // 不透明
  zIndex: 1000,       // 提升层级
});

确保遮罩层 zIndex 高于线路图层(线路建议设为 zIndex: 10 ~ 100)。


✅总结

本组件可作为地图绘制交互模块的通用模板,具备以下优势:

  • ✅ 支持任意 GeoJSON 线路绘制(中心线、边界线)

  • ✅ 支持区域围栏绘制与编辑

  • ✅ 可灵活接入业务平台,适用于智慧城市、交通监控等项目

  • ✅ 支持遮罩层绘制,限制展示区域


📦项目扩展建议

  • 🚀支持多围栏绘制

  • 📊集成围栏属性统计与数据绑定

  • 📍支持围栏内点位聚合或热力图渲染

  • 🌍兼容 Mapbox 或 Cesium 等其他地图平台


如果你对这个项目感兴趣,可以点赞+收藏+关注我,后续我将推出 Vue3 + Mapbox 实现 3D 车辆轨迹回放 的实战教程。

相关推荐
江城开朗的豌豆18 分钟前
Vue的keep-alive缓存揭秘:多出来的生命周期怎么玩?
前端·javascript·vue.js
年纪轻轻就扛不住39 分钟前
keep-alive实现原理及Vue2/Vue3对比分析
前端·javascript·vue.js
江城开朗的豌豆2 小时前
Vue的keep-alive魔法:让你的组件"假死"也能满血复活!
前端·javascript·vue.js
阿珊和她的猫2 小时前
`shallowReactive` 与 `shallowRef`:浅层响应式 API
前端·javascript·vue.js·typescript·状态模式
代码老y3 小时前
Spring Boot + MyBatis + Vue:全栈开发的深度剖析与实践指南
vue.js·spring boot·mybatis
裕波4 小时前
VueConf 2025 来啦,7 月 12 日,深圳见!
前端·vue.js
阿珊和她的猫4 小时前
TodoList 案例(Vue3): 使用Composition API
前端·javascript·vue.js·typescript
海的诗篇_5 小时前
前端开发面试题总结-vue3框架篇(一)
前端·css·vue.js·面试·vue·html
paopaokaka_luck6 小时前
基于SpringBoot+Uniapp的活动中心预约小程序(协同过滤算法、腾讯地图、二维码识别)
java·vue.js·spring boot·小程序·uni-app
一只不会编程的猫6 小时前
Could not find a declaration file for module ‘..XX‘.
linux·前端·vue.js·前端框架·vue·es6