从CircleMarker扩展的标记-如何更改点击区域?

时间:2019-05-09 21:26:30

标签: javascript leaflet

使用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

然后在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); 保持不变(因为这是我为创建图钉而进行的扩展):

MarkerPin click area

其他Leaflet元素(如多边形)的点击区域与形状匹配。话虽这么说,是否可以更改circleMarker的点击区域以匹配我的形状(即使我正在扩展MarkerPin)?

即使无法更改点击区域的形状,我也能够将其向上移动,如下图所示:

MarkerPin recentered click area

甚至,是否有更好的方法来用自定义图标在GeoJSON中呈现多个标记,并使用Leaflet处理其弹出窗口?

修改

为完整起见,这就是我正在使用的(由于https://stackoverflow.com/a/56072877/11064013),它使用了整个图钉区域:

circleMarker

1 个答案:

答案 0 :(得分:1)

通过L.Canvas渲染的矢量层中的点击检测取决于每个矢量层的_containsPoint私有方法。请参见implementation on CircleMarkeron 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]));
    }
})

这应该将点击区域上移或下移。如果想要更好的形状,则必须提供函数的正确实现,该函数将返回是否在形状内的点。