1

I implemented a draggable CircleMarker with popup, however when the circle is moved the popup opens right away. How can I avoid that? Is there a way to cancel the popupopen event?

[Edit]: Ideally the popup should remain in the same status while the marker is being dragged: if the popup is open it should remain open (without ever closing), otherwise should stay closed. In other words, the drag action should only update the position of the marker.

Demo Fiddle

var marker = L.circleMarker([42.5, -73.5], {
  color: '#f03', fillColor: '#f03', fillOpacity: 0.80
})
  .on('mousedown', () => {
    map.dragging.disable();
    map.on('mousemove', trackMouse)
  })
  .bindPopup("The Popup")
  .addTo(map)  

map
  .on('mouseup', () => {
    map.dragging.enable();
    map.removeEventListener('mousemove')
  })


function trackMouse (e) {
  marker.setLatLng(e.latlng);
}
3
  • There is one question with this logic: what should happen when marker is opened and user starts to drag marker: should marker close when dragging or should it stay opened? Please edit your question and clarify this.
    – TomazicM
    Commented Aug 29, 2022 at 19:02
  • @TomazicM probably because I don't really know (nor I found anywhere a clear explanation) what's the firing sequence for all the events involved (map, feature layer, popup, etc.) I'm not sure how that's relevant. The code above should be unaware and unaffected of the state of the popup, shouldn't it? I guess we can say the popup should close before the marker gets dragged, however that should be definable in a callback somewhere, maybe at mousedown?
    – Stefano
    Commented Aug 29, 2022 at 19:17
  • I'm asking to know how would you like it to be. Just edit question and clarify this, if you want the answer.
    – TomazicM
    Commented Aug 29, 2022 at 19:54

1 Answer 1

1

With standard Leaflet popup attached to marker you cannot achieve desired behavior. Solution is to implement your logic of popup opening/closing. Basic principles of doing that could be the following:

  • don't attach popup to the marker, just assign popup text to it through some custom option, like popupTxt;
  • create independent popup that will serve as a base for opening marker popup, with closeOnClick: false option to prevent default behavior;
  • on marker mousedown event prevent it's propagation and save mouse position;
  • on marker mouseup event prevent its propagation and compare cursor position to the saved position from mousedown event; if position is within 1px of saved position, treat it as click and show popup, which has to be done through setTimeout function to execute it outside event processing function;
  • on map mousedown event close popup if it's opened.
  • to prevent popup text being selected when popup is opened during marker drag, user-select: none has to be set for leaflet-popup CSS class.

So code could then look something like this:

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();
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.