这是一篇来自 Dave Leaver 的客座文章,他是一位活跃的 Leaflet 贡献者(特别是,他实现了 0.4 缩放动画的改进),也是目前最好的标记聚类插件的作者,在这篇文章中介绍了这个插件。
几乎所有拥有一张带有标记的地图的人,最终都会出现这些标记重叠的情况。我在 Smartrak 的日常工作中,我们经常有客户在地图上有成千上万的点。当你把它放大时,这些标记都会重叠,使地图看起来很乱很拥挤。还有一种情况是,即使在最大的缩放级别上,标记也会重叠,这就使得无法与它们进行互动。另外,在地图上有大量的标记,通常最终会将性能降低到一个不可接受的水平。
为了改善这一点,许多网站使用了标记聚类,这是一种将每个区段上彼此相近的标记分组的技术。这方面的一个好例子是 Redfin 。我们需要类似的东西,但是在 Leaflet 中。本着开放源代码的精神,我们开发并发布了我们的解决方案,以便每个人都能利用它。因此,我们自豪地介绍 Leaflet.MarkerCluster 。
集群器有各种伟大的内置行为:
使用 Marker Clusterer 很简单,只要用 L.MarkerClusterGroup
替换你现有的 LayerGroup 用法即可:
var markers = new L.MarkerClusterGroup();
markers.addLayer(L.marker([175.3107, -37.7784]));
// add more markers here...
map.addLayer(markers);
你也可以对单个标记和集群使用所有的 FeatureGroup 事件 (另外还有 clusterclick
)。
markers.on('clusterclick', function (a) { alert('Cluster Clicked'); });
markers.on('click', function (a) { alert('Marker Clicked'); });
MarkerClusterGroup
中的标记进行大规模的更新,你可能想把它从地图上删除,改变标记,然后再重新添加它。你可以在 github 下载页面 上下载最新版本。
底层聚类算法( MarkerClusterGroup._cluster
)是普通的贪婪聚类。
foreach marker
如果在聚类距离内有一个聚类,就加入它。
否则,如果在聚类距离内有一个未聚类的标记,就与它形成一个聚类。
第一个聚类步骤是针对最大(最底层)的缩放级别,然后我们对所有产生的标记和聚类进行聚类,生成下一个向上的缩放级别,以此类推,直到我们达到顶部。 这些集群被存储在一棵树上(一个集群包含它的子集群),具有良好的地理空间质量。我们使用这棵树来优化识别在任何特定缩放级别下屏幕上有哪些标记和集群。
L.DistanceGrid
在聚类时提供了一些不错的优化(由 Vladimir 贡献,Leaflet 维护者)。
为了对标记进行聚类,我们需要将每个标记与其他每个标记进行比较,以尝试形成一个聚类。
为了使其更快,我们需要减少我们需要比较的标记的集合。DistanceGrid
通过将所有标记放在一个大小与我们需要搜索的距离相同的网格上来实现。然后,当我们寻找一个要聚类的标记时,我们只需要看我们所在的网格方块和它的近邻的标记。这可能是一个相当大的性能优势,因为我们只看我们有可能形成集群的标记。( 查看数字的初始 PR )
我希望你喜欢使用聚类器,并从中获得你想要的一切。如果你在公共网站上使用它,请 给我发一封邮件 ,这样我可以检查一下,并有可能将其链接到 github 网站上。
如果你有任何问题,也请在 github 页面 上记录一个错误。
Enjoy!
Dave Leaver.