С помощью Leaflet я пытаюсь отобразить много точек (+ 10000) как функцию GeoJSON для повышения производительности. Чтобы добиться лучших результатов, я нашел этот ответ , в котором объясняется, как расширить листлет 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
затем используется в опции 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);
Пока все хорошо. Все данные отображаются правильно.
Моя проблема в том, что область щелчка не обновляется в соответствии с моей новой формой, она остается такой же, как у circleMarker
(потому что это то, что я расширил, чтобы создать мою булавку), показанную красным кружком:
У других элементов Leaflet, таких как многоугольники, область щелчка соответствует их форме. При этом можно ли изменить область щелчка моего MarkerPin
в соответствии с моей формой (даже если я расширяю circleMarker
)?
Даже если невозможно изменить форму области щелчка, я был бы рад возможности немного поднять ее, как показано на рисунке ниже:
Или даже есть ли лучший подход для рендеринга нескольких маркеров в GeoJSON с пользовательским значком и обработки их всплывающих окон с помощью Leaflet?
Редактировать
Для полноты, это то, что я использую (спасибо https://stackoverflow.com/a/56072877/11064013),, который использует всю область вывода:
const MarkerPin = L.CircleMarker.extend({
_updatePath: function() {
this._renderer._updateMarkerPin(this)
},
_containsPoint: function(p) {
let r = this._radius
let insideCircle =
p.add([0, r * 2]).distanceTo(this._point) <= r + this._clickTolerance()
let a = this._point,
b = a.subtract([0.58 * r, r]),
c = a.subtract([-0.58 * r, r])
let insideTriangle = true
let ap_x = p.x - a.x
let ap_y = p.y - a.y
let p_ab = (b.x - a.x) * ap_y - (b.y - a.y) * ap_x > 0
let p_ac = (c.x - a.x) * ap_y - (c.y - a.y) * ap_x > 0
let p_bc = (c.x - b.x) * (p.y - b.y) - (c.y - b.y) * (p.x - b.x) > 0
if (p_ac === p_ab) {
insideTriangle = false
}
if (p_bc !== p_ab) {
insideTriangle = false
}
return insideTriangle || insideCircle
},
})