🎬 效果演示截图(先睹为快)
✨ 功能概览:
-
✅ 鼠标画任意形状多边形;
-
✏️ 点击“修改边界”可拖动顶点;
-
🟥 点击“遮罩”后地图除多边形区域外变红;
-
✂️ 点击“剪切”后仅显示选中区域;
-
❌ 点击“取消”按钮恢复地图。
📸 示例截图如下(运行后效果类似):
🧭 项目背景
在地图可视化开发中,我们常常需要:
-
用户绘制特定区域(如选区、高亮区);
-
支持图形的交互编辑;
-
结合遮罩或剪切来突出或限制显示区域。
本篇教程将通过 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]) return
mask = 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]) return
crop = 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 |
📚 参考资料
-
🔗 ol-ext 官方 Demo
✅ 总结
本文通过 Vue 3 + OpenLayers + ol-ext 完整实现了:
-
🖌 绘制任意形状区域;
-
✏️ 对区域编辑修改;
-
🟥 地图遮罩显示;
-
✂️ 地图裁剪显示;
-
♻️ 功能复原与清除。
以上能力在城市管理、规划分析、地图可视化等场景中有广泛应用,值得收藏并实践!
如果你觉得本篇内容对你有帮助,欢迎点赞、收藏、评论支持一下!
后续我将继续分享 Vue + OpenLayers 的实战经验与技巧,如图层控制、热力图、轨迹动画等,欢迎关注!