101.在 Vue 3 + OpenLayers 使用 declutter 避免文字标签重叠
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 = pointImg
const 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 开发技巧!