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

leaflet中绘制轨迹线的大量轨迹点,解决大量 marker 绑定 tooltip 同时显示导致的性能问题

优化思路:获取屏幕可视区范围,判断tooltip 的经纬度是否在可视区范围内,如果在就显示,如果不在就隐藏,达到优化效果

代码:

/*** Leaflet Tooltip 视窗优化演示** 这个文件展示了如何在其他 Leaflet 项目中实现类似的 tooltip 优化方案* 主要解决大量 marker 绑定 tooltip 导致的性能问题** 使用方法:* 1. 引入此文件中的优化函数* 2. 替换原有的 bindTooltip 调用* 3. 在地图事件中调用更新方法*//*** 防抖* @param {*} fn 需要防抖的方法* @param {*} delay 防抖时间* @param {*} atOnce 是否需要立即执行* @returns* how use vue3+ts* (1) 首次执行 设置时间内只执行首次 适用于新增、设置、修改等*  let addTest = _.myDebounce(function(e: any) {addNum();}, 2000,true);let addNum = () => {console.log("打印参数");};**(2)设置时间内只执行最后一次  适用于筛选等let addTest = _.myDebounce(function(e: any) {addNum();}, 2000,false);let addNum = () => {console.log("打印参数");};*/
const myDebounce = (fn, time, atOnce) => {let delay = time || 200;let timer = null;let count = 0;return function () {const _this = this;const args = arguments;// 如果是立即执行if (atOnce) {// 第一次直接执行不用等if (count == 0) {fn.apply(_this, args);count++;if (timer) {clearTimeout(timer);}timer = setTimeout(function () {count = 0;// fn.apply(_this, args);}, delay);}} else {if (timer) {clearTimeout(timer);}timer = setTimeout(function () {fn.apply(_this, args);}, delay);}};
};/*** Tooltip 视窗优化类* 管理 Leaflet 地图中的 tooltip 显示优化*/
export class LeafletTooltipOptimizer {constructor(map) {this.map = map;this.visibleTooltipMarkers = new Set(); // 可视区域内已绑定tooltip的markerthis.allTooltipMarkers = new Map(); // 所有需要tooltip的marker信息this.updateDebounced = myDebounce(this.updateVisibleTooltips.bind(this), 200, false);this.initEventListeners();}/*** 初始化地图事件监听*/initEventListeners() {if (this.map) {this.map.on("moveend", this.updateDebounced);this.map.on("zoomend", this.updateDebounced);this.map.on("resize", this.updateDebounced);console.log("Tooltip优化事件监听器已初始化");}}/*** 检查marker是否在可视区域内*/isMarkerInViewport(marker) {if (!marker || !this.map) return false;try {const bounds = this.map.getBounds();const markerLatLng = marker.getLatLng();return bounds.contains(markerLatLng);} catch (error) {console.warn("检查marker可视性时出错:", error);return false;}}/*** 为marker绑定tooltip(延迟绑定)* @param {L.Marker} marker* @param {string} content tooltip内容* @param {Object} options tooltip选项*/bindTooltipIfVisible(marker, content, options = {}) {if (!marker) return;// 存储tooltip配置信息this.allTooltipMarkers.set(marker, { content, options });// 如果在可视区域内且未绑定tooltip,则绑定if (this.isMarkerInViewport(marker) && !this.visibleTooltipMarkers.has(marker)) {marker.bindTooltip(content, options);this.visibleTooltipMarkers.add(marker);}}/*** 更新可视区域内的tooltip绑定*/updateVisibleTooltips() {if (!this.map || this.allTooltipMarkers.size === 0) return;try {this.allTooltipMarkers.forEach((tooltipConfig, marker) => {const isVisible = this.isMarkerInViewport(marker);const hasTooltip = this.visibleTooltipMarkers.has(marker);if (isVisible && !hasTooltip) {// 进入可视区域,绑定tooltipmarker.bindTooltip(tooltipConfig.content, tooltipConfig.options);this.visibleTooltipMarkers.add(marker);} else if (!isVisible && hasTooltip) {// 离开可视区域,解绑tooltipmarker.unbindTooltip();this.visibleTooltipMarkers.delete(marker);}});} catch (error) {console.error("更新可视tooltip时出错:", error);}}/*** 清理marker的tooltip记录* @param {L.Marker} marker*/cleanupMarkerTooltip(marker) {if (marker) {this.allTooltipMarkers.delete(marker);this.visibleTooltipMarkers.delete(marker);}}/*** 清理所有tooltip记录*/clearAllTooltips() {this.allTooltipMarkers.clear();this.visibleTooltipMarkers.clear();}/*** 清理事件监听器*/destroy() {if (this.map) {this.map.off("moveend", this.updateDebounced);this.map.off("zoomend", this.updateDebounced);this.map.off("resize", this.updateDebounced);}this.clearAllTooltips();}/*** 获取统计信息*/getStats() {return {totalMarkers: this.allTooltipMarkers.size,visibleMarkers: this.visibleTooltipMarkers.size,hiddenMarkers: this.allTooltipMarkers.size - this.visibleTooltipMarkers.size,};}
}/*** 使用示例:** // 1. 创建优化器实例* const tooltipOptimizer = new LeafletTooltipOptimizer(map);** // 2. 使用优化后的tooltip绑定方法* markers.forEach(marker => {*     const tooltipContent = `<div>纬度: ${marker.getLatLng().lat}</div><div>经度: ${marker.getLatLng().lng}</div>`;*     const tooltipOptions = {*         permanent: false,*         direction: "top",*         offset: [0, -10]*     };**     // 替换原来的 marker.bindTooltip(content, options)*     tooltipOptimizer.bindTooltipIfVisible(marker, tooltipContent, tooltipOptions);* });** // 3. 在需要清理marker时调用* map.eachLayer(layer => {*     if (layer instanceof L.Marker) {*         tooltipOptimizer.cleanupMarkerTooltip(layer);*         map.removeLayer(layer);*     }* });** // 4. 组件销毁时清理* tooltipOptimizer.destroy();*/export default LeafletTooltipOptimizer;

http://www.xdnf.cn/news/1210123.html

相关文章:

  • 车载刷写架构 --- 刷写思考扩展
  • Redis的持久化策略-AOF和RDB(详细图解)
  • Java面试宝典:MySQL8新特性底层原理
  • Vue2 vs Vue3:核心差异与升级亮点
  • DeepSeek MoE 技术解析:模型架构、通信优化与负载均衡
  • 飞书 —— 多维表格 —— AI生成
  • 系统学习算法:专题十五 哈希表
  • 数据库02 网页html01 day44
  • 抵御酒店管理系统收银终端篡改攻击 API 加密的好处及实现——仙盟创梦IDE
  • 如何创建一个 Solana 钱包?
  • 文件操作与IO流
  • 如何编写好的测试用例?
  • 泛微E9 引入高版本spring导致webservices接口报错
  • 青少年软件编程图形化Scratch等级考试试卷(四级)2025年6月
  • SpringBoot之起步依赖
  • 在 Web3 时代通过自我主权合规重塑 KYC/AML
  • java导出pdf(使用html)
  • Java:为什么需要通配符捕获(wildcard capture)
  • 【WRF-Chem 实例1】namelist.input 详解- 模拟CO2
  • 【跨国数仓迁移最佳实践3】资源消耗减少50%!解析跨国数仓迁移至MaxCompute背后的性能优化技术
  • 机器学习第二课之线性回归的实战技巧
  • Three.js 性能优化全面指南:从几何体合并到懒加载资源
  • Ubuntu上开通Samba网络共享
  • nodejs 实现Excel数据导入数据库,以及数据库数据导出excel接口(核心使用了multer和node-xlsx库)
  • CTF Misc入门篇
  • 创建型设计模式-工厂方法模式和抽象工厂方法模式
  • Ubuntu卡在启动画面:显卡驱动与密码重置
  • 青少年软件编程图形化Scratch等级考试试卷(二级)2025年6月
  • Spring Boot 防重放攻击全面指南:原理、方案与最佳实践
  • Python爬虫分析B站番剧播放量趋势:从数据采集到可视化分析