6

I have added a GeoJSON file consisting of multiple polygons to a leaflet map. Now after clicking on any of those polygons I don't want Leaflet to accept any subsequent click events for this specific polygon anymore. This is what I have tried to no avail:

leafletGeoJsonLayer.on('click', function (e) {
  ...color clicked polygon red or green...
  e.layer.options.interactive = false; //don't accept further click events for this polygon
}

Any ideas how to achieve that?

enter image description here

2 Answers 2

9

One possible solution would be to use some custom polygon/layer property, like for example wasClicked (name can be any, as long is does not conflict with standard Leaflet layer properties), to mark the fact that polygon/layer was already clicked. If wasClicked is true, further processing is skipped.

Code could then look something like this:

leafletGeoJsonLayer.on('click', function (e) {
  var layer = e.target;
  if (layer.wasClicked) return;

  layer.wasClicked = true;
  ...
}

Other possible solution would be to cancel layer click event processing with the .off method. In this case code could look something like this:

function processGeoJsonClick(e) {
  var layer = e.target;
  layer.off('click', processGeoJsonClick);
  ...
}

leafletGeoJsonLayer.on('click', processGeoJsonClick);
3

I see (at least) four ways of achieving this, none of them being really clean:


The (default) L.SVG vector renderer applies the interactive option only when a vector is added to the renderer. Thus, removing and re-adding the polygon should do the trick.

leafletGeoJsonLayer.on('click', function (e) {
  e.layer.options.interactive = false;
  leafletGeoJsonLayer.removeLayer(e.layer).addLayer(e.layer);
}

The (non-default) L.Canvas renderer checks for the interactive option at every pointer interaction. Thus, telling your GeoJSON vectors to draw inside a L.Canvas should do the trick.

var canvasRenderer = L.canvas();
var leafletGeoJsonLayer = L.geoJson({ 
  style: function() { 
    return { renderer: canvasRenderer, /* etc */ };
  }
});

The (default) L.SVG vector renderer relies on an internal addInteractiveTarget/removeInteractiveTarget logic to dispatch leaflet-decorated events to the appropriate objects. It's possible to manually detach the SVG DOM node for the polygon for this logic, by reading the code of the L.SVG renderer regarding removing a vector layer and using an undocumented private property of vector layers:

leafletGeoJsonLayer.on('click', function (e) {
  e.layer.removeInteractiveTarget(e.layer._path);
}

The path will still dispatch pointer events, but they'll be detached from the Leaflet logic, and thus ignored by any event handlers set up for the GeoJSON group.


Assuming a SVG renderer, since paths are actually DOM nodes (and the target of the original DOM events), it's possible to update their CSS properties. For this problem specifically, the pointer-events CSS property is of interest.

leafletGeoJsonLayer.on('click', function (e) {
  e.originalEvent.target.style.pointerEvents = 'none';
}

That should be equivalent to

leafletGeoJsonLayer.on('click', function (e) {
  e.layer._path.style.pointerEvents = 'none';
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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