一种基于Leaflet.Legend的图例动态更新方法

news2025/2/10 23:41:01

目录

前言

一、场景再现

1、需求描述

2、核心方法介绍

3、存在的问题

二、问题解决

1、重复解决办法

2、图例不展示解决办法

3、成果展示

三、总结


前言

        在当今数字化时代,地理信息系统(GIS)技术已经广泛应用于各个领域,从城市规划到环境监测,从交通管理到资源勘探等。而地图可视化作为 GIS 的重要组成部分,为用户提供了直观、便捷的方式来展示和分析地理空间数据。Leaflet 作为一种轻量级、开源的地图库,因其简单易用、高度可定制化以及良好的兼容性,受到了众多开发者的青睐,被广泛应用于各种地图应用的开发中。而在地图可视化中,图例的作用不可忽视。它为用户提供了地图上各种符号、颜色和图层所代表的含义,帮助用户更好地理解和解读地图信息。

        关于如何在Leaflet中进行图例生成,原博文介绍:LeafLet加载自定义Legend的设计与实现。在后面的项目当中基本都是一次性生成图例,然后在地图上展示。然而,在最近的实际开发过程中,遇到了一个棘手的问题:Leaflet 的图例无法动态更新。当地图上的数据发生变化,例如添加或移除图层、修改图层样式、更新数据源等时,图例却无法及时反映这些变化,这给用户带来了极大的不便,也影响了地图应用的用户体验和实用性。因此需要程序能根据变化或者事件响应动态更新。在实际实践中我们发现,leaflet.legend的图例动态更新存在一定的局限性。它通常是基于初始加载时的图层和样式信息来生成图例的,而当这些信息发生变化时,图例并不会自动重新生成或更新。这使得开发者在面对动态数据和交互式地图时,难以实现图例与地图的同步更新。

        本篇文章将深入探讨解决 Leaflet.Legend 图例无法动态更新的一种方法。我们将从问题出发,分析现有解决方案的不足之处,然后详细介绍一种基于事件监听和动态渲染机制的方法。通过这种方法,我们可以在地图数据发生变化时,自动检测并动态更新图例,确保图例始终与地图上的数据保持一致。我们将通过实际代码示例和测试结果,展示该方法的有效性和可行性,并探讨其在不同应用场景中的适用性和优化方向。

        通过本文的介绍,希望能够为广大的 Leaflet 开发者提供一种全新的思路和实用的解决方案,帮助他们在地图开发过程中更好地应对图例动态更新的挑战,提升地图应用的质量和用户体验。同时,也期待与更多开发者交流和分享经验,共同推动 Leaflet 技术的发展和创新。

一、场景再现

        本节将从需求场景、核心方法介绍、存在的问题三个方面对开发过程遇到的问题进行讲解。通过本节的阐述,可以让朋友们对leaflet.legend的核心方法有更详细的认识,通过结合核心API方法和存在的问题,为下一步问题的解决奠定方向和基础。

1、需求描述

        在以往的一些WebGIS应用展示中,比如展示地震的震级、风景区的等级等,这些图例信息往往都是固定的,我们可以将地震震级分成不同的震级,比如3级以下,3-5级,5-7级,7级以上等。又比如在风景区的等级中中的5A、4A、3A、2A、1A等,如下图。

        这些图例在地图进行展示时基本上已经是固定的,后续需要动态变化的只是调整数据的输出,而图例基本上是不会改变的。暂且我们将这些图例成为静态图例。与这种需求不一样的是,如果在应用中,我们需要动态切换数据图层,比如从行政区划图层切换到土地利用图层,图例不仅内容也要发生变化,即维度的变化。同时在渲染的样式、具体的图例文字方面都要进行变化,内容上从行政区划名称切换成不同的土地利用类型。还有一些场景是跟随时间维度变化的,随着时间的推移,图例会新增或者移除部分老的图例。比如在在风景区分级中,需要将2A和3A级景区进行合并。从而减少图例的展示个数。这样的场景非常多,不管是基于事件驱动还是时间驱动,都会对关联的图例的有所影响。以上就是本文遇到的几个需求场景,这里只描述了其中的一两种,现实当中肯定有更多的场景,就不注意列举了。

2、核心方法介绍

        与后端的OOP编程思想相类似,前端也是采用类似OOP的思想进行开发。因此对相关的对象的属性和方法进行封装。关于leaflet.legend的属性,这里不再进行赘述,但是对核心的API方法还是需要进行详细叙述。因为在进行图例内容的动态生成中,肯定需要调用leaflet.legend提供的方法来实现图例的动态生成的。这里将详细介绍其相关的方法。

        除了对象的Options配置参数外,以上就是比较重要的几个API方法。 下面将对图例对象的初始化、图例容器构建、图例绘制、事件响应、重绘等几个方法进行介绍。帮助大家对组件有更深入的理解。我们来看一下在原来的代码中是如何将图例添加到地图中的,原始方法代码如下:

function updateLegend(legendData){
	var legend = L.control.Legend({
		position: "bottomright",
		collapsed: false,
		symbolWidth: 24,
		opacity: 1,
		title:"图例",
		column: 2,
		legends: legendData
	});
	legend.addTo(map);
}

        在Javascript中进行代码断点来看一下将legend对象添加到地图后,会发生什么? 首先将调用的是initialize()方法,可以在参数入口处看到传入的参数。

        在将图例符号进行清空后,将进行图例容器对象的创建,调用的_buildContainer()方法,以此来绑定和展示图例信息。

        请注意,在这里创建用于图例展示的div容器(这个方法很重要,请注意这个方法,在这个方法里,会创建容器,在后面的问题解决过程中会涉及重复对象的创建,因此在调整时需要规避这个问题), 在这个方法中,通过循环配置参数中的不同图例信息,循环构建图例信息。构建图例元素的方法是:_buildLegendItems();

        通过以上对核心方法的介绍,相信大家对于组件的相关API有了进一步的认识。在后面的问题解决阶段还会对这些方法有所涉及。

3、存在的问题

        在最开始开发的时候,往往由于没有深入的研究相关的API,极容易出现一些错误。比如图例越来越多,在地图上的位置都展示不了了。又或者是事件触发后,相应的图例并没有生成,没有任何效果,当前图例没有生成,或者是产生了报错。下面我们对这几种情况分别进行说明,如最开始的代码所示,第一种情况就是图例越来越多。

function updateLegend(legendData){
	var legend = L.control.Legend({
		position: "bottomright",
		collapsed: false,
		symbolWidth: 24,
		opacity: 1,
		title:"图例",
		column: 2,
		legends: legendData
	});
	legend.addTo(map);
}

        程序运行后,可以在图例的展示栏中看到图例越来越多,虽然新的产生了,但老的没有替换到。如下图所示:

         第二种情况是开发的同学稍微了解组件的方法,在获得legend对象后,重新对图例数据进行赋值,然后调用重绘的方法,代码如下:

function updateLegend(legendData){
	if(undefined == legend){
		legend = L.control.Legend({
			position: "bottomright",
			collapsed: false,
			symbolWidth: 24,
			opacity: 1,
			title:"图例",
			column: 2,
			legends: legendData
		});
	}else{
		//step1、重新设置数据
		legend.options.legends = legendData;
		//step2、重新绘制
		legend.redraw();
	}
	legend.addTo(map);
}

        咋一看起来,似乎是非常好的解决办法,但是实际运行后却是以下的情况:

        不仅没有出现新的图例,老的图例都消失了。 在查看浏览器的控制台时,可以发现以下的报错:

        更详细的是以下的代码行中出现问题,在这个重绘的方法中,其调用的是构建单个图例的重绘。在方法调用时需要传入容器对象和当前的图例对象。在redraw方法中,传入了空的值。类似于报了空指针异常。

        以上就是在开发当中极易碰到的问题,这里先讲讲遇到的两个问题场景,如果您开发当中也遇到这种问题,不妨来这里看看。 

二、问题解决

        本节将重点围绕第一节中的遇到的问题,重点对发现或者产生的问题进行解决。主要是围绕图例的重复生成、图例的正确重绘方法进行介绍,在介绍的过程中又会回顾到前面的API核心接口讲解。因此这是一个动手的过程,希望你可以跟着一起来动手实践,纸上得来终觉浅,绝知此事要躬行。只有经过自己的亲自动手,才能彻底得掌握如何应对和解决。

        为了模拟图例的动态生成,在Leaflet页面上,新增了一个“图例更新”的按钮,用这个按钮的模拟事件来进行模拟需要动态切换的场景。模拟的按钮及其相关处理事件如下:

<div class="center-flex">
	<input type="button" class="opt_button" value="更新图例" onclick="updateLegendEvent()"></input>
</div>

        其处理的回调方法如下,请注意在程序中设置一个标志位,用于切换不同的图例数据对象,在真实情况中,可以通过ajax来请求服务的接口后获得:

function updateLegendEvent(){
	var updateLegendData;
	if(sign == 0 ){
		updateLegendData = [{
			label: "位置",
			type: "image",
			url: "marker/marker-red.png"
		}, {
			label: "Marker2",
			type: "image",
			url: "marker/purple.png"
		}];
		sign = 1;
	} else {
		updateLegendData = initLegendData;
		sign = 0;
	}
	updateLegend(updateLegendData);
}

        在有了事件的驱动之后,接下来就是图例对象的定义和展示。下面将深入如何避免在上一节中遇到的问题,针对性的提出解决办法。

1、重复解决办法

        为了解决在图例生成时的重复问题,我们可以在进行图例对象生成时只生成一份,后续则在之前的对象中调用方法来修改相应的参数,以此来达到相应的目的。这个代码比较简单,在前面的方法中提到过,在初始化时增加一个判断,如果为空就创建对象,否则使用原来的对象:

function updateLegend(legendData){
	if(undefined == legend){
		legend = L.control.Legend({
			position: "bottomright",
			collapsed: false,
			symbolWidth: 24,
			opacity: 1,
			title:"图例",
			column: 2,
			legends: legendData
		});
	}else{
		//step1、重新设置数据
		legend.options.legends = legendData;
		//step2、重新绘制
		legend.redraw();
	}
	legend.addTo(map);
}

        通过以上的代码就能避免图例对象重复创建的问题。 

2、图例不展示解决办法

        在解决图例的重复问题之后,又迎来一个新的难题,即图例在切换后不展示了。这又是什么问题呢?其实答案在第一节中的第三小节中已经有说明。在上面的代码中,我们调用的是redraw的方法,而这个方法最终调用的是_buildLegendItems: function (legendContainer, legend) {}方法,在这个方法中,需要传入一个图例容器和一个图例对象,而在redraw方法中并没有涉及这两个对象。因此才报的错。那么如何避免这种问题呢?解铃还须系铃人,要想解决图例不展示的问题,还得找到核心的问题,在前面的核心方法中,我们知道一套完备的可视化展示流程。即initialize方法调用_buildContainer方法,同时在_buildContainer方法中又会循环调用_buildLegendItems。通过这种方法,就会传入容器和图例对象,按照这种调用思路,在设置新的数据后,程序需要做的就是重新初始化,这样就会清空当前的图例对象,同时生成最新的图例。代码如下:

function updateLegend(legendData){
	if(undefined == legend){
		legend = L.control.Legend({
			position: "bottomright",
			collapsed: false,
			symbolWidth: 24,
			opacity: 1,
			title:"图例",
			column: 2,
			legends: legendData
		});
	}else{
		//动态加载图例的实现方式
		//step1、重新设置数据
		legend.options.legends = legendData;
		//step2、重新初始化(重新绘制)
		legend.initialize();
	}
	legend.addTo(map);
}

        将代码进行改造后,图例可以正常展示了,但是重复的问题又产生了。如下图:

        难道这种问题没有解决办法了么?仔细再想想,在初始化的方法中,依然还会创建容器对象出来,来看看它的源代码:

        可以看到这个图例容器依然会重新创建,因此还是会产生重复。最终的答案是在每次初始化前将容器移除掉。代码很简单,如下:

function updateLegend(legendData){
	if(undefined == legend){
		legend = L.control.Legend({
			position: "bottomright",
			collapsed: false,
			symbolWidth: 24,
			opacity: 1,
			title:"图例",
			column: 2,
			legends: legendData
		});
	}else{
		//动态加载图例的实现方式
		//step1、重新设置数据
		legend.options.legends = legendData;
		//step2、销毁图例容器,保证不重复
		legend.getContainer().remove();
		//step3、重新初始化(重新绘制)
		legend.initialize();
	}
	legend.addTo(map);
}

3、成果展示

        经过上述的改造,就能完美的解决图例重复已经切换后不展示的问题,下面来看一下最终的成果,点击“图例更新”按钮后,图例可以进行不停的切换,基本实现我们的需求,图例不会重复生成,也不会不见,控制台也不会报错,最终效果如下图所示:

三、总结

        以上就是本文的主要内容,本篇文章将深入探讨解决 Leaflet.Legend 图例无法动态更新的一种方法。我们将从问题出发,分析现有解决方案的不足之处,然后详细介绍一种基于事件监听和动态渲染机制的方法。通过这种方法,我们可以在地图数据发生变化时,自动检测并动态更新图例,确保图例始终与地图上的数据保持一致。我们将通过实际代码示例和测试结果,展示该方法的有效性和可行性,并探讨其在不同应用场景中的适用性和优化方向。

        通过本文的介绍,希望能够为广大的 Leaflet 开发者提供一种全新的思路和实用的解决方案,帮助他们在地图开发过程中更好地应对图例动态更新的挑战,提升地图应用的质量和用户体验。同时,也期待与更多开发者交流和分享经验,共同推动 Leaflet 技术的发展和创新。行文仓促,定有许多不足之处,如有不足在此恳请各位专家朋友批评指正,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2295309.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【韩顺平linux】部分上课笔记整理

整理一下一些韩顺平老师上课时候的笔记 课程&#xff1a;【小白入门 通俗易懂】韩顺平 一周学会Linux linux环境&#xff1a;使用阿里云服务器 笔记参考 &#xff1a; [学习笔记]2021韩顺平一周学会Linux 一、自定义函数 基本语法 应用实例&#xff1a; 计算两个参数的和…

CPP集群聊天服务器开发实践(一):用户注册与登录

目录 1 客户端用户注册与登录 1.1 主要思想 1.2 网络层 1.3 业务层 1.4 数据层 1.5 测试结果 1 客户端用户注册与登录 1.1 主要思想 实现网络层、业务层、数据层的解耦&#xff0c;提高系统的可维护性。 网络层&#xff1a;主要实现对客户端连接、客户端读写请求的捕获…

学JDBC 第二日

数据库连接池 作用 使数据库连接达到重用的效果&#xff0c;较少的消耗资源 原理 在创建连接池对象时&#xff0c;创建好指定个数的连接对象 之后直接获取连接对象使用即可&#xff0c;不用每次都创建连接对象 从数据库连接池中获取的对象的close方法真的关闭连接对象了吗…

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据

一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址&#xff1a; https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动&#xff0c;会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…

【C语言标准库函数】三角函数

目录 一、头文件 二、函数简介 2.1. 正弦函数&#xff1a;sin(double angle) 2.2. 余弦函数&#xff1a;cos(double angle) 2.3. 正切函数&#xff1a;tan(double angle) 2.4. 反正弦函数&#xff1a;asin(double value) 2.5. 反余弦函数&#xff1a;acos(double value)…

Redisson全面解析:从使用方法到工作原理的深度探索

文章目录 写在文章开头详解Redisson基本数据类型基础配置字符串操作列表操作映射集阻塞队列延迟队列更多关于Redisson详解Redisson 中的原子类详解redisson中的发布订阅模型小结参考写在文章开头 Redisson是基于原生redis操作指令上进一步的封装,屏蔽了redis数据结构的实现细…

声明式导航,编程式导航,导航传参,下拉刷新

1.页面导航 1.声明式导航 1.1跳转到tabBar页面 1.2跳转到非tabBar页面 1.2后退导航 、 2.编程式导航 2.1跳转到tabBar页面 2.1跳转到非tabBar页面 2.3后退导航 3.导航传参 3.1声名式导航传参 3.2编程式导航传参 3.3在onLoad中接受参数 4.下拉刷新 4.1回顾下拉刷新…

金和OA C6 DownLoadBgImage任意文件读取漏洞

金和OA C6 DownLoadBgImage任意文件读取漏洞 漏洞描述 金和C6数据库是一款针对企业信息化管理而设计的高级数据库管理系统&#xff0c;主要应用于企业资源规划&#xff08;ERP&#xff09;、客户关系管理&#xff08;CRM&#xff09;以及办公自动化&#xff08;OA&#xff09…

激活函数篇 03 —— ReLU、LeakyReLU、ELU

本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归&#xff1a;Sigmoid函数在分类问题中的应用 整流线性单位函数&#xff08;Rectified Linear Unit, ReLU&#xff09;&#xff0c;又称修正线性单元&a…

Kafka 入门与实战

一、Kafka 基础 1.1 创建topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test --create 1.2 查看消费者偏移量位置 kafka-consumer-groups.bat --bootstrap-server localhost:9092 --describe --group test 1.3 消息的生产与发送 #生产者 kafka-cons…

5 计算机网络

5 计算机网络 5.1 OSI/RM七层模型 5.2 TCP/IP协议簇 5.2.1:常见协议基础 一、 TCP是可靠的&#xff0c;效率低的&#xff1b; 1.HTTP协议端口默认80&#xff0c;HTTPSSL之后成为HTTPS协议默认端口443。 2.对于0~1023一般是默认的公共端口不需要注册&#xff0c;1024以后的则需…

VMware虚拟机安装、创建Ubuntu虚拟机及汉化设置全流程详细教程

一、安装VMware Workstation 下载VMware 访问官网&#xff1a;https://www.vmware.com 选择适合的版本&#xff08;如 Workstation Pro 或 VMware Player&#xff0c;后者免费&#xff09;。完成下载后运行安装程序。 网盘下载&#xff1a; 链接: https://pan.baidu.com/s/1MQ…

21.2.7 综合示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 【例 21.7】【项目&#xff1a;code21-007】填充职员表并打印。 本例使用到的Excel文件为&#xff1a;职员信息登记表.xlsx&#x…

【大模型】DeepSeek与chatGPT的区别以及自身的优势

目录 一、前言二、核心技术对比2.1 模型架构设计2.1.1 ChatGPT的Transformer架构2.1.2 DeepSeek的混合架构 2.2 训练数据体系2.2.1 ChatGPT的数据特征2.2.2 DeepSeek的数据策略 三、应用场景对比3.1 通用场景表现3.1.1 ChatGPT的强项领域3.2.2 DeepSeek的专项突破 3.3 响应效率…

burpsuite抓取html登陆和上传数据包

一、burpsuite抓取html登陆数据包 1、先写一个html格式的登陆页面 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><title>这是标签</title></head> <body> <hr><!-- 登陆表单 …

Linux 安装 Ollama

1、下载地址 Download Ollama on Linux 2、有网络直接执行 curl -fsSL https://ollama.com/install.sh | sh 命令 3、下载慢的解决方法 1、curl -fsSL https://ollama.com/install.sh -o ollama_install.sh 2、sed -i s|https://ollama.com/download/ollama-linux|https://…

使用Ollama本地部署deepseek

1、下载安装Ollama 前往下载页面 https://ollama.com/download下载好安装包&#xff0c;如同安装软件一样&#xff0c;直接安装即可 win中默认为C盘&#xff0c;如果需要修改到其他盘&#xff0c;查找具体教程 运行list命令&#xff0c;检查是否安装成功 2、修改模型下载的…

如何在RTACAR中配置IP多播(IP Multicast)

一、什么是IP多播 IP多播&#xff08;IP Multicast&#xff09;是一种允许数据包从单一源地址发送到多个目标地址的技术&#xff0c;是一种高效的数据传输方式。 多播地址是专门用于多播通信的IP地址&#xff0c;范围从 224.0.0.0到239.255.255.255 与单播IP地址不同&#x…

2025年最新版武书连SCD期刊(中国科学引文数据库)来源期刊已更新,可下载PDF版!需要的作者进来了解~

2025年最新版武书连SCD期刊&#xff08;中国科学引文数据库&#xff09;来源期刊已更新&#xff01; 官网是不提供免费查询的。小编给大家两个路径&#xff0c;无需下载PDF&#xff0c;随时随地都能查25版SCD目录。 路径一&#xff1a;中州期刊联盟官网&#xff0c;25版SCD目…

存储异常导致的Oracle重大生产故障

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验 Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯…