How to Make interactive Leaflet Tiles from GridLayer

Viewed 873

By extending GridLayer, you can return a custom div element to load your own visual for each tile based on the coordinate. For what I want to do, I want to make each tile responsive so it does something when you hover over it. However, adding this attribute to the div doesn't do anything, same with clicking and other interactivity. It seems like Leaflet just renders them separately and returns the composite image they produce, erasing my attributes.

I have to instead pull the event from the map, find the tile I clicked, change the data for that tile, and reload the layer so that the changes show. Is there a faster and cleaner way to do this?

1 Answers

First, be aware that Leaflet sets the CSS pointer-events property to none to the tile containers:

.leaflet-tile-container {
    pointer-events: none;
}

Even if you attach event handlers to the tiles, no events will reach those event handlers.

You can, however, override the value of that CSS property using a CSS class on the GridLayer and CSS rules, or by setting the value of that property on a per-tile basis (BTW do read the note about pointer events targeting descendants of an element with pointer-events: none).

So I can do something like

grid.createTile = function (coords) {
  var tile = L.DomUtil.create('div', 'tile-hoverable');

  // Ensure that this tile will respond to pointer events,
  // by setting its CSS 'pointer-events' property programatically
  tile.style.pointerEvents = 'initial';

  // Attach some event handlers to this particular tile
  L.DomEvent.on(tile, 'mouseover', function(){
    tile.style.background = 'red';
  });
  L.DomEvent.on(tile, 'mouseout', function(){
    tile.style.background = 'transparent';
  });

  return tile;
};

You can see a working example here.

Related