leaflet - Leaflet + Supercluster:L.marker 的 autoPan 不工作
问题描述
我正在使用 mapbox 超集群库来聚类相当大量的点数据,并在闪亮的应用程序中使用传单将其绘制出来。如果位置错误,则显示这些点maxZoom
并且可以为用户拖动。Mapbox supercluster 使用静态 kdbush 空间索引,因此每次L.marker
移动 a 时,都会重新加载集群(在我的情况下这不是问题,因为 supercluster 非常快)。
但是,只能L.marker
在可见地图边界内拖动使用超集群。这是有道理的,因为L.marker
's 仅针对可见地图边界动态生成。如果L.marker
使用选项定义,则在将其拖到可见地图范围之外{draggable:true,autoPan:true}
时会发生错误:L.marker
Uncaught TypeError: t is null
leaflet 1.3.3/dist/leaflet.js:5
leaflet 1.3.3/dist/leaflet.js:5
at https://unpkg.com/leaflet@1.3.3/dist/leaflet.js:5
_adjustPan https://unpkg.com/leaflet@1.3.3/dist/leaflet.js:5
_adjustPan self-hosted:891
_adjustPan self-hosted:844
或在我闪亮的应用程序中,我收到以下错误:
Uncaught TypeError: Cannot set property '_leaflet_pos' of null
at Object.Lt [as setPosition] (eval at <anonymous> (jquery.min.js:2), <anonymous>:5:9959)
at e._adjustPan (eval at <anonymous> (jquery.min.js:2), <anonymous>:5:71149)
将某种 autopan forL.marker
用于超集群会非常酷。我知道用户可以缩小以将点拖动到预期位置。在我的情况下,这并不是一个真正的选择,因为在可见地图范围内很快就会有太多的点会减慢地图的平移速度(这就是我首先使用聚类的原因)。
我试图在拖动事件期间使用panTo
layer.on('drag',function(e){
//console.log('marker dragstart event');
var position=e.target.getLatLng();
map.panTo(new L.latLng(position.lat,position.lng));
});
但这似乎以某种方式停止了拖动事件。
我的问题是:有没有办法让自动平移L.marker
与超集群一起使用?
我在下面设置了一个最小的可重现示例。这个例子绘制了一个单点 ( var marker
) 以及三个点 ( var markers
) 与超集群。可以将单个点拖到可见地图范围之外,而聚类点则不能。
var map = L.map('map').setView([51.505, -1.09], 9);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
var marker = new L.marker([51.505, -1.09],{
draggable: true,
autoPan:true
}).bindPopup('autopan working').addTo(map);
// Empty Layer Group that will receive the clusters data on the fly.
var markers = L.geoJson(null, {
pointToLayer: createClusterIcon,
onEachFeature: onEachFeature
}).addTo(map);
var clusterData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties":{
"id":0
},
"geometry": {
"type": "Point",
"coordinates": [-1.0,51.5]
}
},
{
"type": "Feature",
"properties":{
"id":1
},
"geometry": {
"type": "Point",
"coordinates": [-1.1,51.6]
}
},
{
"type": "Feature",
"properties":{
"id":2
},
"geometry": {
"type": "Point",
"coordinates": [-0.9,51.4]
}
}
]
}
function onEachFeature(f, layer) {
//add drag event
layer.on('drag',function(e){
//console.log('marker dragstart event');
//var position=e.target.getLatLng();
//map.panTo(new L.latLng(position.lat,position.lng));
});
layer.on('dragend',function(e){
//console.log('marker dragend event');
var changedPos = e.target.getLatLng();
//console.log('new location '+changedPos);
//load cluster again
clusterData.features[f.properties.id].geometry.coordinates[1]=changedPos.lat;
clusterData.features[f.properties.id].geometry.coordinates[0]=changedPos.lng;
index.load(clusterData.features);
update();
});
}
// Update the displayed clusters after user pan / zoom.
map.on('moveend', update);
function update() {
if (!ready) return;
var bounds = map.getBounds();
var bbox = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()];
var zoom = map.getZoom();
var clusters = index.getClusters(bbox, zoom);
//console.log('clusters '+clusters);
markers.clearLayers();
markers.addData(clusters);
}
// Zoom to expand the cluster clicked by user.
markers.on('click', function(e) {
//console.log('check data' + e.layer.feature.properties.cluster_id);
var clusterId = e.layer.feature.properties.cluster_id;
var center = e.latlng;
var expansionZoom;
if (clusterId) {
expansionZoom = index.getClusterExpansionZoom(clusterId);
map.flyTo(center, expansionZoom);
}
});
var ready = false;
//load data
const index = new Supercluster({
radius: 150,
maxZoom:10
});
index.load(clusterData.features);
ready= true;
update();
function createClusterIcon(feature, latlng) {
if (!feature.properties.cluster){
return L.marker(latlng,{draggable:true,autoPan:true}); //add autoPan:true
}
var count = feature.properties.point_count;
var size =
count < 100 ? 'small' :
count < 1000 ? 'medium' : 'large';
var icon = L.divIcon({
html: '<div><span>' + feature.properties.point_count_abbreviated + '</span></div>',
className: 'marker-cluster marker-cluster-' + size,
iconSize: L.point(40, 40)
});
return L.marker(latlng, {
icon: icon
});
}
#map {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
<script src="https://unpkg.com/supercluster@7.1.0/dist/supercluster.min.js"></script>
<link href="https://cdn.rawgit.com/mapbox/supercluster/v4.0.1/demo/cluster.css" rel="stylesheet"/>
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css" rel="stylesheet"/>
<div id="map"></div>
解决方案
推荐阅读
- java - 如何在其他片段中重用布局
- python - 为什么当我省略“from tkinter import *”时会出现错误?
- wordpress - htaccess 重定向 301 有效,但 RewriteRule 无效
- javascript - redux-thunk axios async 中必须如何操作?
- python - 如何在加入时拆分 sqlalchemy 中的文本列以供使用?
- angular - Angular 11 在安装节点模块时无法解析依赖树
- github-actions - GitHub 操作中奇怪的布尔求值
- autodesk-forge - 无法在 MarkupsCore 扩展中为“EVENT_EDITMODE_CREATION_END”添加事件侦听器
- r - 从R中的矩阵创建公式
- node.js - 身份验证中的护照奇怪行为