当前位置: 首页 > article >正文

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 组件显示时间,并设置 fillbackgroundFill 等属性
  • 避免重叠: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 开发技巧!


http://www.kler.cn/a/584707.html

相关文章:

  • 【C】初阶数据结构9 -- 直接插入排序
  • 集合进阶——数据结构
  • 洛谷P10576 [蓝桥杯 2024 国 A] 儿童节快乐
  • React篇之three渲染
  • WebRTC技术在音视频处理上的难点剖析:EasyRTC嵌入式视频通话SDK的优化策略
  • Appium等待机制--强制等待、隐式等待、显式等待
  • 一次 诡异 的 JVM OOM 事故 原创
  • Vue3:组件通信方式
  • 【工具使用】IDEA社区版如何使用JDK原生命令:从IDEA到命令行的开发技巧
  • 完美解决ElementUI中树形结构table勾选问题
  • 商品管理中的“DeepSeek” AI赋能零售品牌释放利润空间
  • Spring Boot 常用注解的分类及简明解释
  • Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录
  • 50.HarmonyOS NEXT 登录模块开发教程(四):状态管理与数据绑定
  • 网络安全工具nc(NetCat)
  • Android7上移植I2C-tools
  • 探索 PyTorch 中的 ConvTranspose2d 及其转置卷积家族
  • SolidWorks中文完整版+教程百度云资源分享
  • 【JavaScript 】1. 什么是 Node.js?(JavaScript 服务器环境)
  • 【Flutter】第一次textEditingController.text获取到空字符串