一种解决Leaflet中Divicon城市气温标注空间重叠的办法
目录
二、基于rbush和Leaflet.LayerGroup.Collision的解决办法
2、Leaflet.LayerGroup.Collision.js
前言
又是一年的1024,各位程序员朋友们又迎来了一年一度的程序员节。此刻的你又在做什么呢?是在工位上奋力敲击,用键盘创造作品亦或者处理bug呢。下午刚跟产品达成的一致,希望明天不要再变,希望验收要求不要太变态,哎。万一要变,除了响应又有什么办法呢。或者在进行测试,性能测试也好,功能测试也好。跟开发的同学关系还好吗?是不是又在撕扯一些问题究竟要不要改或者优先级要不要定这么高。是否在专注的进行产品设计,将用户的需求转换成产品文档。这又是第几稿了呢?还记得上次远程会议上,用户信誓旦旦的保证,坚决不会再加需求了。望着邮箱中又发过来的紧急邮件,朋友你还好吗?是否在机房紧张的排查问题呢?系统莫名的停服了半个小时,头顶为数不多的细发也在瑟瑟发抖,今晚或许又是一个通宵。哎,作为运维,不就是扮演救火队去专门灭火嘛?先抽根烟,稳稳神,慢慢排查吧。不是增长了经验就是增长了怒火。哎,1024。年年岁岁都有1024,一样的工作,一样的状态。有同学说,已经开始了滴滴和外卖半年了。体力在慢慢转好。调侃也罢,事实也罢。真心的祝所有的程序员朋友们开心快乐,祝大家生活、工作愉快。
以上皆是赘言,算个起题。记得在之前的一篇博客中曾讲解如何在Leaflet中进行DivIcon的标注开发。虽然成功的实现了需求,但是不知道各位朋友们有没有实际运行过。在地图上进行点标注之后,如果进行缩放,很难免就会有标注的重叠,掌握空间可视化的朋友应该都知道。随着地图的不妨缩小,比例尺也在不断的变化。而我们的DivIcon由于是已经创建出来的html页面元素,正常情况它是不会变化的。因此在进行空间可视化时就会出现以下的情况。各个标签就完全重叠到了一起。密密麻麻的,特别不好看。以我国东南部一些城市的天气情况综合WebGIS可视化效果,来看下面的效果图:
可以看到,这些网页的标注都重叠到了一起。虽然我们可以放大地图,以此来让这些标签分开。这样子的效果就比较清爽,关键的信息没有被遮挡。城市的气温信息很友好,看起来很直观。效果如下所示:
那么有没有一种合理的方式,就像之前我们分享过的标签自动避让的功能,基于Canvas的标注标签自动避让呢,在空间中碰撞之后就会有标签隐藏起来。但是很遗憾,在Leaflet官方的API中,是没有这种功能的,除了针对Marker有点聚合的功能,针对divIcon的聚合貌似没有。本文即重点介绍如何在Leaflet中进行DidIcon信息标注时,应对空间对象重叠的问题,如何去解决。文章首先介绍一些可能的解决办法,然后介绍如何基于rbush和Leaflet.LayerGroup.Collision.js这两个组件来实现,最后介绍具体的实现方法即实现成果。如果您对如何解决DivIcon的空间重叠问题有兴趣,不妨来这里看看。
一、一些解决办法
在空间中进行大量的信息标注是一种很常见的需求,由空间的相邻特性所决定的其位置的相邻。由此带来的一些空间重叠的问题。也是很常见的一种现象。这里围绕重叠标注的问题,来寻找一些可行的解决方案。
1、marker的聚类
对marker进行聚类是一种常见的操作。markercluster是将这些点先聚合成一起,然后伴随着地图的方法按照位置来进行展示。如下图所示:
这其实也是一种解决办法,即将这些空间标注使用聚类的方式来实现,对于聚集在一起的位置信息,就组合在一起,都不进行展示, 但是这样聚类的实现效果带来的就是信息都不展示。只有地图放大后才会进行展示。
2、使用leaflet-canvas-label
如果想把点信息都展示出来,但是对于中文标注又可以实现一个避让的另一种方法就是使用leaflet-canvas-label。在前面的博客中也介绍过这些知识,实现的效果如下:
使用leaflet-canvas-label的标签避让实现方式,虽然可以把信息都展示出来,但是其内部是基于Canvas来实现的,因此想实现自定义的div,如divicon的实现方式就不行,因为在canvas中,它的实现原理是在绘制标签时进行宽度判断。在其源码中可以看到如下代码:
使用leaflet.canvaslabel来实现标注避让虽然可以实现需求,但是很明显的是。不支持我们的divicon的标绘方式,因此这个方案暂且搁置。
3、使用Zoom和样式控制
在web页面中,我们可以对样式进行控制,比如我们可以控制在不同的zoom中,我们的标签不显示出来,在zoom=10级的情况下,将标签的display设置为true,将标签展示出来。而在zoom< 10的情况下,调用样式的display为false,这样就可以实现divicon标注的显示与隐藏。同样,缺点也是非常明显的,不能精确的控制,而且不好预估zoom,对于后期的扩展和修复是比较麻烦的。因此我们需要一种更加灵活的方式。既能实现divicon的动态展示,也能实现重叠对象的问题解决。
二、基于rbush和Leaflet.LayerGroup.Collision的解决办法
既然上面的方案或多或少都有一些缺陷,那么如何来实现这种需求呢?这里分享一种方法。即使用rbush和Leaflet.LayerGroup.Collision.js来进行支持。本节就对这两个外部的组件来进行说明。
1、关于rbush
RBush 是一个高性能的 JavaScript 库,用于点和矩形的 2D 空间索引。它基于具有批量插入支持的优化 R-tree 数据结构。空间索引是点和矩形的特殊数据结构,它允许你非常有效地执行诸如 “此边界框内的所有项目” 之类的查询(例如,比遍历所有项目快数百倍)。它最常用于地图和数据可视化。RBush,作为一款专门为JavaScript设计的空间索引库,以其卓越的性能和灵活性,在众多开发者中赢得了广泛的好评。它不仅能够高效地处理二维空间中的点和矩形数据,更因其采用了优化的R树数据结构而具备了处理大规模数据集的能力。RBush的一个显著优势在于它的批量插入功能,这使得在处理大量数据时,无需逐个插入即可实现高效的数据索引建立,极大地提高了数据处理的速度与效率。对于那些需要频繁进行数据查询、插入或删除操作的应用场景来说,RBush无疑是一个理想的选择。
在这里采用rbush,是为了在前端构建一个2d的Rtree来进行空间数据的查询。关于rbush的要求大家可以在官网网站上查询。
。这里注意一下,在进行空间重叠数据的分析时,rbush的版本不能使用太高。需要的朋友可以在博客下面留言,看到会发送可用的版本。 关于rbush的核心方法,这里不细细展开,后面可以找时间来进行深入讲解。
2、Leaflet.LayerGroup.Collision.js
Leaflet.LayerGroup.Collision.js组件与marker的聚类组件差不多,主要作用就是生成前端聚类。Leaflet.LayerGroup.Collision.js的官方地址如下
:在src中,包含了具体的组件,感兴趣的可以自己打开源码进行学习。 到这里,对使用的rbush和Leaflet.LayerGroup.Collision进行了简单的介绍,下面将结合实际的例子来进行说明如何进行代码的开发。
三、解决标签重叠的具体实现
在对涉及的技术进行了简单介绍后,下面来对如何使用rbush和Leaflet.LayerGroup.Collision来进行实例开发,以解决标签重叠的问题。实现标签的碰撞检测,满足用户的需求。
1、添加元数据
介绍完我们的用户场景后,我们来准备用户的基础元数据。这里以城市天气气温信息的展示。首先包括城市的国籍、城市具体信息、时间和温度。当然,这些数据,您可以从自己的后台接口或者从互联网公开的接口来获取。这里我们仅演示如何进行标绘,对如何获取接口不进行赘述。如果接口中的字段有所修改,请在代码实践过程中进行合理调整相关字段。下面给大家分享具体的元数据,代码如下:
2、添加到collisionLayer中
与前面介绍过的divicon标注方法一致,在这里还是要根据坐标点生成marker,然后在marker中设置divicon元素信息。关键代码如下:
首先我们会生成一个包含对象margin距离的图层组,通过图层组来进行marker数据绑定。在实际创建marker对象时,会根据这个margin来进行范围创建,代码如下:
很明显,在这里将我们传入的组件的宽度加上本身组件的偏移量来生成bbox,然后将bbox添加到rbush中进行判断。将当前图层添加到rbush建立的rtree中,见下面的_maybeAddLayerToRBush方法。
3、实现效果
实践是检验真理的唯一标准,在经过上面的编程后我们基本实现了对divicon的标注重叠。下面来看一下具体的效果。
大家在上图的效果中就可以看到,在地图上重叠的divicon数据已经完全分开了。目前只展示了两个城市的信息。接着我们使用鼠标滚轮来进行地图的方法,看随着地图的放大,其它隐藏的标注是否会展示出来。
可以很明显的看到,随着地图的放大,原先隐藏的标签现在都展示出来了。进一步放大后看一下实际的效果如何?
可以直观的看到,经过上面的开发步骤,我们已经成功的实现DivIcon标注的重叠隐藏和展示。非常完美的实现了我们的需求。
四、总结
以上就是本文的主要内容,本文即重点介绍如何在Leaflet中进行DidIcon信息标注时,应对空间对象重叠的问题,如何去解决。文章首先介绍一些可能的解决办法,然后介绍如何基于rbush和Leaflet.LayerGroup.Collision.js这两个组件来实现,最后介绍具体的实现方法即实现成果。当然,在本文的实现过程中,我们还可以结合数据检索,将marker进行空间查询过滤,减少数据量的返回,提高渲染的速度。
当然,rbush这个组件不仅可以在我们这个场景中进行使用,可以在更多的空间查询中来使用更高效的算法,辅助前端进行数据的高效检索。更多好的使用方式,欢迎大家去探索。行文仓促,定有许多不足之处,还肯定各位朋友和专家在评论区留下批评意见,不生感激。
- 点赞
- 收藏
- 关注作者
评论(0)