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 车辆轨迹回放 的实战教程。

相关推荐
Yehong5 小时前
nuxt实现50个前端小创意(1)——前端基础学习
前端·vue.js
拉不动的猪5 小时前
回顾vue3组件在运行过程中的编译提升
前端·vue.js·trae
胡斌附体8 小时前
vue组件和插件的区别
vue.js·组件·插件·vue.component·vue.use
layman05288 小时前
Vue中的 VueComponent
前端·javascript·vue.js
mqiqe9 小时前
vue发版html 生成打包到docker镜像进行发版
vue.js·docker·html
疯狂的沙粒12 小时前
React与Vue的内置指令对比
开发语言·前端·javascript·vue.js
GISer_Jing13 小时前
低代码——表单生成器Form Generator详解(二)——从JSON配置项到动态渲染表单渲染
前端·vue.js
CXH72814 小时前
从零开始创建 Vue 3 开发环境并构建第一个 Demo
前端·javascript·vue.js
夏木。。。14 小时前
vue+elementPlus实现表格展示序号并且翻页不重新排
vue.js·elementplus
小张快跑。15 小时前
<el-date-picker>配置禁用指定日期之前的时间选择(Vue2+Vue3)
前端·javascript·vue.js