📌 本文將介紹如何在 Vue 3 中使用 OpenLayers 實現:
1)用戶可在地圖上繪制矩形;
2)自動截取該區域地圖為圖片;
3)一鍵保存為本地 PNG 圖片。
?效果如下圖所示
🧠一、前言
在地圖類 Web 應用中,我們經常有這樣的需求:
-
想截取某個區域的地圖;
-
想讓用戶自由框選區域后下載;
-
或作為報告附圖、圖片處理的輸入。
本文就帶大家用 Vue 3 + OpenLayers 來實現“繪制矩形并截圖保存”功能,完整、實用、即插即用。
🔧二、核心技術棧
技術 | 說明 |
---|---|
Vue 3 | 前端框架,使用 Composition API |
OpenLayers | 地圖引擎,支持繪制、圖層操作等 |
Element Plus | UI 組件庫,用于按鈕控制 |
📦三、項目初始化
推薦使用 Vite 快速構建 Vue 3 項目:
npm create vite@latest vue3-openlayers-demo --template vue
cd vue3-openlayers-demo
npm install
安裝必要依賴:
npm install ol element-plus
在 main.js
中引入 Element Plus:
import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus)
??四、完整實現代碼(Composition API 寫法)
我們將完整功能封裝在一個組件中,以下為 MapScreenshot.vue
代碼:
<!--* @Author: 彭麒* @Date: 2025/5/15* @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="drawBox">繪制矩形截圖</el-button><el-button type="danger" size="small" @click="clearSource">清除圖層</el-button></h4><div id="vue-openlayers"></div></div>
</template><script setup>
import { onMounted, ref } from 'vue'import 'ol/ol.css'
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import VectorLayer from 'ol/layer/Vector'
import OSM from 'ol/source/OSM'
import VectorSource from 'ol/source/Vector'
import Draw, { createBox } from 'ol/interaction/Draw'
import { Style, Fill, Stroke } from 'ol/style'// 創建響應式引用
const map = ref(null)
const draw = ref(null)
const source = new VectorSource({ wrapX: false })// 初始化地圖
const initMap = () => {const raster = new TileLayer({source: new OSM(),})const vector = new VectorLayer({source,style: new Style({fill: new Fill({color: 'rgba(0,0,0,0)',}),stroke: new Stroke({color: 'darkgreen',width: 2,}),}),})map.value = new Map({target: 'vue-openlayers',layers: [raster, vector],view: new View({projection: 'EPSG:4326',center: [116.1206, 39.034996],zoom: 10,}),})
}// 清除圖層
const clearSource = () => {source.clear()
}// 繪制矩形并截圖保存
const drawBox = () => {if (draw.value) {map.value.removeInteraction(draw.value)}draw.value = new Draw({source,type: 'Circle',geometryFunction: createBox(),})map.value.addInteraction(draw.value)draw.value.on('drawend', (e) => {if (draw.value) {map.value.removeInteraction(draw.value)}map.value.renderSync()const extent = e.feature.getGeometry().getExtent()const leftTop = map.value.getPixelFromCoordinate([extent[0], extent[3]])const bottomRight = map.value.getPixelFromCoordinate([extent[2], extent[1]])const width = Math.abs(bottomRight[0] - leftTop[0])const height = Math.abs(bottomRight[1] - leftTop[1])const minx = leftTop[0]const miny = leftTop[1]const mapCanvas = document.getElementsByClassName('ol-layer')[0].children[0]const ctx = mapCanvas.getContext('2d')const imageData = ctx.getImageData(minx, miny, width, height)const canvas = document.createElement('canvas')canvas.width = widthcanvas.height = heightcanvas.getContext('2d').putImageData(imageData, 0, 0)const dataUrl = canvas.toDataURL()const link = document.createElement('a')link.download = '我的圖片.png'link.href = dataUrllink.click()})
}onMounted(() => {initMap()
})
</script><style scoped>
.container {width: 840px;height: 590px;margin: 50px auto;border: 1px solid #42B983;
}
#vue-openlayers {width: 800px;height: 420px;margin: 0 auto;border: 1px solid #42B983;position: relative;
}
</style>
🎁五、功能說明
功能 | 說明 |
---|---|
繪制矩形 | 鼠標在地圖拖動繪制一個矩形區域 |
截圖區域 | 自動計算該區域對應的 canvas 像素范圍 |
保存圖片 | 提取該 canvas 區域內容,生成 PNG 并下載 |
清除圖層 | 一鍵清空繪制的圖形,保持地圖干凈 |
🧩六、關鍵技術解析
? createBox()
與 Draw
import { createBox } from 'ol/interaction/Draw'
-
createBox()
是一個 geometryFunction,配合type: 'Circle'
使用時,會把圓形繪制轉換為矩形繪制。 -
非常巧妙地實現了“繪制矩形”的能力!
? getPixelFromCoordinate()
實現截圖區域定位
將地理坐標轉換為像素坐標,才能從 canvas 中精確提取圖像:
map.getPixelFromCoordinate([x, y])
🧪七、實測效果截圖
🔚八、總結
本文介紹了如何在 Vue 3 中集成 OpenLayers,并實現一個非常實用的截圖保存功能。通過繪制矩形,可以對地圖任意區域進行截圖提取,非常適合:
-
地圖分析應用;
-
地理標注報告;
-
自定義地圖素材裁剪;
📎九、聯系方式
🧑?💻作者:彭麒
📧Email:1062470959@qq.com
📌CSDN主頁:歡迎點贊 + 收藏 + 關注
如本文對你有幫助,歡迎留言交流!