使用Leaflet,我试图将很多点(+ 10000)渲染为GeoJSON功能,以提高性能。为了获得更好的结果,我发现this answer指导如何扩展Leaflet的circleMarker
来改变其形状,如下所示:
L.Canvas.include({
_updateMarkerPin: function(layer) {
if (!this._drawing || layer._empty()) {
return
}
var p = layer._point,
ctx = this._ctx,
r = layer._radius
this._drawnLayers[layer._leaflet_id] = layer
ctx.beginPath()
ctx.moveTo(p.x, p.y)
ctx.lineTo(p.x - 0.58 * r, p.y - r)
ctx.arc(p.x, p.y - 2 * r, r, -Math.PI * 1.161, Math.PI * 0.161)
ctx.closePath()
this._fillStroke(ctx, layer)
},
})
const MarkerPin = L.CircleMarker.extend({
_updatePath: function() {
this._renderer._updateMarkerPin(this)
},
})
这是我的MarkerPin形状:
然后在MarkerPin
的{{1}}选项中使用 L.GeoJSON
,如下所示:
pointToLayer
到目前为止,一切都很好。所有数据都会正确渲染。
我的问题是:点击区域没有根据我的新形状进行更新,而是像红色圆圈所示的那样const myPointToLayer = (feature, latlng) => {
var markerParams = {
radius: 16,
stroke: true,
weight: 2,
opacity: 0.4,
fillOpacity: 0.9,
}
return new MarkerPin(latlng, markerParams)
}
const myOnEachFeature = (feature, layer) => {
layer.bindPopup('Clicked me!')
}
L.geoJSON(data, {
pointToLayer:myPointToLayer,
onEachFeature: myOnEachFeature,
}).addTo(map);
保持不变(因为这是我为创建图钉而进行的扩展):>
其他Leaflet元素(如多边形)的点击区域与形状匹配。话虽这么说,是否可以更改circleMarker
的点击区域以匹配我的形状(即使我正在扩展MarkerPin
)?
即使无法更改点击区域的形状,我也能够将其向上移动,如下图所示:
甚至,是否有更好的方法来用自定义图标在GeoJSON中呈现多个标记,并使用Leaflet处理其弹出窗口?
修改
为完整起见,这就是我正在使用的(由于https://stackoverflow.com/a/56072877/11064013),它使用了整个图钉区域:
circleMarker
答案 0 :(得分:1)
通过L.Canvas
渲染的矢量层中的点击检测取决于每个矢量层的_containsPoint
私有方法。请参见implementation on CircleMarker
或on Polyline
。
每次user clicks on a L.Canvas
renderer, the renderer loops through all the layers in it,并询问他们“用户在像素p
中做了某件事-这是您的吗?”?致电_containsPoint
必须回答。
因此,您必须为_containsPoint
类实施MarkerPin
,例如,
const MarkerPin = L.CircleMarker.extend({
_updatePath: function() {
this._renderer._updateMarkerPin(this)
},
_containsPoint: function(p) {
return L.CircleMarker.prototype._containsPoint.call(this, p.subtract([0, 10]));
}
})
这应该将点击区域上移或下移。如果想要更好的形状,则必须提供函数的正确实现,该函数将返回是否在形状内的点。