Con la ventana emergente estándar de Leaflet adjunta al marcador no se puede lograr el comportamiento deseado. La solución es implementar su lógica de apertura/cierre del popup. Los principios básicos para hacerlo podrían ser los siguientes:
- no adjuntar la ventana emergente al marcador, sólo asignar el texto emergente a través de alguna opción personalizada, como
popupTxt
;
- crear una ventana emergente independiente que servirá de base para abrir la ventana emergente del marcador, con
closeOnClick: false
para evitar el comportamiento por defecto;
- en el marcador
mousedown
evitar su propagación y guardar la posición del ratón;
- en el marcador
mouseup
evitar su propagación y comparar la posición del cursor con la posición guardada de mousedown
si la posición está dentro de 1px de la posición guardada, se trata como un clic y se muestra la ventana emergente, lo que debe hacerse a través de setTimeout
para ejecutarlo fuera de la función de procesamiento de eventos;
- en el mapa
mousedown
evento cerrar la ventana emergente si se abre.
- para evitar que se seleccione el texto de la ventana emergente cuando ésta se abre al arrastrar el marcador,
user-select: none
tiene que ser fijado para leaflet-popup
Clase CSS.
Así que el código podría ser algo así:
CSS:
.leaflet-popup {
user-select: none;
}
JS:
var marker = L.circleMarker([42.5, -73.5], {
color: '#f03',
fillColor: '#f03',
fillOpacity: 0.80,
popupTxt: 'This is my popup'
}).addTo(map);
var mousePos = null;
var popup = L.popup({
closeOnClick: false
});
function trackMouse (e) {
circleMarker.setLatLng(e.latlng);
popup.setLatLng(e.latlng)
}
marker.on('mousedown', (e) => {
L.DomEvent.stopPropagation(e);
map.dragging.disable();
map.on('mousemove', trackMouse);
mousePos = {x: e.containerPoint.x, y: e.containerPoint.y};
})
marker.on('mouseup', (e) => {
L.DomEvent.stopPropagation(e);
map.dragging.enable();
map.removeEventListener('mousemove');
var x = e.containerPoint.x;
var y = e.containerPoint.y;
if ((Math.abs(x - mousePos.x) < 1) && (Math.abs(y - mousePos.y) < 1) && !popup.isOpen()) {
setTimeout(() => {
popup.setLatLng(e.latlng)
.setContent(e.target.options.popupTxt)
.openOn(map);
}, 1);
}
})
map.on('mousedown', (e) => {
if (popup.isOpen()) popup.close();
});