1. 前言
在使用 OpenLayers 進行地圖開發時,我們經常需要在地圖上添加點、線、區域等圖形,并給它們附加文字標簽。但當地圖上的標注較多時,文字標簽可能會發生重疊,導致用戶無法清晰地查看地圖信息。
幸運的是,OpenLayers 提供了 declutter
選項,能夠有效地避免文字標簽的重疊問題。本文將介紹如何在 Vue 3 + OpenLayers 項目中使用 declutter
,并通過示例代碼展示如何添加帶有時間標簽的軌跡點。
2. declutter
介紹
declutter
是 OpenLayers VectorLayer
(矢量圖層)的一個屬性,專門用于處理標注(文本或圖標)的重疊問題。如果 declutter: true
,OpenLayers 會自動調整標注的顯示方式,避免文本或圖標重疊在一起,提高地圖的可讀性。
3. 項目環境
- Vue 3 + Composition API
- OpenLayers
- Vite
安裝 OpenLayers
npm install ol
4. 代碼實現
4.1 創建 Vue 組件
我們創建一個 Vue 組件,在其中初始化 OpenLayers 地圖,并使用 declutter
避免標注重疊。
完整代碼
<!--* @Author: 彭麒* @Date: 2025/3/13* @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使用declutter,避免文字標簽重疊</div></div><div id="vue-openlayers"></div></div>
</template><script setup>
import "ol/ol.css";
import {onMounted, ref} from "vue";
import {Map, View} from "ol";
import Tile from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Style from "ol/style/Style";
import Icon from "ol/style/Icon";
import Text from "ol/style/Text";
import Fill from "ol/style/Fill";
import Stroke from "ol/style/Stroke";
import Feature from "ol/Feature";
import {Point, LineString} from "ol/geom";
import startPoint from "@/assets/OpenLayers/startPoint.png";
import endPoint from "@/assets/OpenLayers/endPoint.png";
import pointImg from "@/assets/OpenLayers/point.png";
const map = ref(null);
const trackSource = new VectorSource();
const markersData = ref([[111.44, 24.18, 1604627953],[112.26, 24.48, 1604714353],[113.96, 24.65, 1604800753],[113.44, 24.78, 1604887153],[113.44, 24.98, 1605059953],[113.54, 25.68, 1605146353],
]);const setTrackStyle = (text, img) => {return [new Style({image: new Icon({src: img,anchor: [0.5, 0.5],scale: 0.2,}),text: new Text({font: "12px sans-serif",maxAngle: 30,offsetY: 20,text: text,fill: new Fill({color: "#fff"}),backgroundFill: new Fill({color: "rgba(255,0,0,0.6)"}),backgroundStroke: new Stroke({color: "rgba(255,0,0,0.6)", width: 8}),}),}),];
};const showTrace = (data) => {const lineFeature = new Feature(new LineString(data));lineFeature.setStyle(new Style({stroke: new Stroke({color: "#00f", width: 2})}));trackSource.addFeature(lineFeature);const features = [];data.forEach((point, index) => {let img;if (index === 0) img = startPoint;else if (index === data.length - 1) img = endPoint;else img = pointImgconst feature = new Feature({geometry: new Point([point[0], point[1]]),data: point,});const time = new Date(point[2] * 1000).toISOString().split("T")[0];feature.setStyle(setTrackStyle(`時間: ${time}`, img));features.push(feature);});trackSource.addFeatures(features);
};const initMap = () => {const OSMlayer = new Tile({source: new OSM()});const trackLayer = new VectorLayer({source: trackSource,declutter: true, // 避免標簽重疊});map.value = new Map({target: "vue-openlayers",layers: [OSMlayer, trackLayer],view: new View({center: [113.448, 23.986],zoom: 7,projection: "EPSG:4326",}),});
};onMounted(() => {initMap();showTrace(markersData.value);
});</script><style scoped>
.container {width: 840px;height: 590px;margin: 50px auto;border: 1px solid #42B983;
}#vue-openlayers {width: 800px;height: 470px;margin: 0 auto;border: 1px solid #42B983;position: relative;
}
</style>
5. 代碼解析
5.1 setTrackStyle
方法
該方法用于給軌跡點設置樣式:
- 圖標:設置
Icon
作為點的標識 - 文本:使用
Text
組件顯示時間,并設置fill
、backgroundFill
等屬性 - 避免重疊:OpenLayers 通過
declutter
自動處理文字的布局,防止多個標注擠在一起
5.2 showTrace
方法
- 繪制軌跡線路:使用
LineString
創建軌跡線 - 添加軌跡點:遍歷
markersData
數據,為每個點創建Feature
- 設置時間標簽:使用
setTrackStyle
給每個點添加時間信息
5.3 initMap
方法
- 創建地圖實例
- 添加
OSM
瓦片地圖 - 添加
VectorLayer
(啟用declutter
)
6. declutter
前后效果對比
在未啟用 declutter
時,多個標注可能會重疊在一起,影響閱讀:
開啟 declutter
后,OpenLayers 會自動優化文本排布,防止文字疊加:
7. 結論
本文介紹了如何在 Vue 3 + OpenLayers 項目中使用 declutter
避免文字標簽重疊。declutter
是 OpenLayers 提供的強大功能,能夠自動優化地圖標注,使得地圖數據更加清晰可讀。希望本文對你有所幫助!
如果覺得有用,請點贊收藏支持!🚀
📢 關注我,獲取更多前端 & GIS 開發技巧!