133.在 Vue3 中使用 OpenLayers 实现画多边形、任意编辑、遮罩与剪切处理功能
🎬 效果演示截图(先睹为快)
✨ 功能概览:
-
✅ 鼠标画任意形状多边形;
-
✏️ 点击“修改边界”可拖动顶点;
-
🟥 点击“遮罩”后地图除多边形区域外变红;
-
✂️ 点击“剪切”后仅显示选中区域;
-
❌ 点击“取消”按钮恢复地图。
📸 示例截图如下(运行后效果类似):
🧭 项目背景
在地图可视化开发中,我们常常需要:
-
用户绘制特定区域(如选区、高亮区);
-
支持图形的交互编辑;
-
结合遮罩或剪切来突出或限制显示区域。
本篇教程将通过 Vue3 + OpenLayers + ol-ext 来实现这套完整功能,适合用于城市规划、环境监控、园区展示等场景。
🧱 技术栈介绍
技术 | 说明 |
---|---|
Vue 3 | 使用 Composition API 编写组件 |
OpenLayers | 地图渲染与交互处理 |
ol-ext | OpenLayers 的扩展库,支持遮罩/剪切等高级效果 |
Element Plus | UI 组件库,支持按钮操作 |
📦 初始化项目
安装必要依赖:
npm install ol ol-ext element-plus
💻 核心功能组件源码(DrawMaskCrop.vue)
以下是完整的组件代码,使用 Vue Composition API 编写,实现画图、编辑、遮罩、剪切、清除等功能。
<!--* @Author: 彭麒* @Date: 2025/5/29* @Email: 1062470959@qq.com* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。-->
<template><div class="container"><div class="w-full flex justify-center flex-wrap"><div class="font-bold text-[24px]">在Vue3中使用OpenLayers画多边形,任意编辑,并做遮罩剪切处理</div></div><h4><el-button type="primary" size="small" @click="drawPolygon">画多边形</el-button><el-button type="warning" size="small" @click="startModify">修改边界</el-button><el-button type="warning" size="small" @click="endModify">停止编辑</el-button><el-button type="success" size="small" @click="mapmask">遮罩</el-button><el-button type="success" size="small" @click="mapcrop">剪切</el-button><el-button type="danger" size="small" @click="cancelMaskCrop">取消</el-button></h4><div id="vue-openlayers"></div></div>
</template><script setup>
import {onMounted } from 'vue'
import 'ol/ol.css'
import 'ol-ext/dist/ol-ext.min.css'
import { Map, View } from 'ol'
import OSM from 'ol/source/OSM'
import TileLayer from 'ol/layer/Tile'
import LayerVector from 'ol/layer/Vector'
import SourceVector from 'ol/source/Vector'
import Fill from 'ol/style/Fill'
import Stroke from 'ol/style/Stroke'
import Style from 'ol/style/Style'
import Mask from 'ol-ext/filter/Mask'
import Crop from 'ol-ext/filter/Crop'
import Draw from 'ol/interaction/Draw'
import Modify from 'ol/interaction/Modify'
let map,osmLayer,mask,crop,draw,modify = null
const source = new SourceVector({ wrapX: false })
const initMap = () => {osmLayer = new TileLayer({source: new OSM()})const vectorLayer = new LayerVector({source,style: new Style({fill: new Fill({ color: 'transparent' }),stroke: new Stroke({ width: 2, color: 'blue' })})})map = new Map({layers: [osmLayer, vectorLayer],view: new View({center: [116, 39.5],zoom: 8,projection: 'EPSG:4326'}),target: 'vue-openlayers'})
}const drawPolygon = () => {source.clear()if (draw) map.removeInteraction(draw)draw = new Draw({source,type: 'Polygon'})map.addInteraction(draw)draw.on('drawend', () => {map.removeInteraction(draw)})
}const startModify = () => {modify = new Modify({ source })map.addInteraction(modify)
}const endModify = () => {if (modify) {map.removeInteraction(modify)}
}const cancelMaskCrop = () => {if (mask) mask.set('active', false)if (crop) crop.set('active', false)
}const mapmask = () => {cancelMaskCrop()const features = source.getFeatures()if (!features[0]) returnmask = new Mask({feature: features[0],wrapX: true,inner: false,fill: new Fill({ color: [255, 0, 0, 0.5] })})osmLayer.addFilter(mask)
}const mapcrop = () => {cancelMaskCrop()const features = source.getFeatures()if (!features[0]) returncrop = new Crop({feature: features[0],wrapX: true,inner: false})osmLayer.addFilter(crop)
}onMounted(() => {initMap()
})
</script><style scoped>
.container {width: 840px;height: 570px;margin: 50px auto;border: 1px solid #42B983;
}#vue-openlayers {width: 800px;height: 400px;margin: 0 auto;border: 1px solid #42B983;position: relative;
}
</style>
🔍 核心功能说明
功能 | 实现方式 |
---|---|
多边形绘制 | 使用 ol/interaction/Draw |
图形编辑 | 使用 ol/interaction/Modify |
遮罩效果 | 使用 ol-ext/filter/Mask |
剪切效果 | 使用 ol-ext/filter/Crop |
功能取消 | 设置遮罩与剪切 filter 的 active=false |
📚 参考资料
-
🔗 OpenLayers 官网
-
🔗 ol-ext 官方 Demo
-
🔗 Element Plus 组件库
-
📖 EPSG:4326 vs EPSG:3857 坐标系介绍
✅ 总结
本文通过 Vue 3 + OpenLayers + ol-ext 完整实现了:
-
🖌 绘制任意形状区域;
-
✏️ 对区域编辑修改;
-
🟥 地图遮罩显示;
-
✂️ 地图裁剪显示;
-
♻️ 功能复原与清除。
以上能力在城市管理、规划分析、地图可视化等场景中有广泛应用,值得收藏并实践!
如果你觉得本篇内容对你有帮助,欢迎点赞、收藏、评论支持一下!
后续我将继续分享 Vue + OpenLayers 的实战经验与技巧,如图层控制、热力图、轨迹动画等,欢迎关注!