1

I am using Leaflet.VectorGrid to display a Vector Tiles layer that is loaded from pbf tiles from a tile server.

<html>

<head>
    <title>Vector Map</title>
<body>
<script>
        var map = L.map('map', {
            maxZoom: 21
        });

        var tilesurl = "https://example.de/vector/{z}/{x}/{y}.pbf";
        var vectorTileStyling = { ... }; // my styling goes here
        var VectorTileOptions = {
            rendererFactory: L.canvas.tile,
            interactive: true,
            attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://www.mapbox.com/about/maps/">MapBox</a>',
            vectorTileLayerStyles: vectorTileStyling,
        };
        var myPbfLayer = L.vectorGrid.protobuf(tilesurl, VectorTileOptions);

        L.control.layers({
            "Vector Layer": myPbfLayer
        }, {}, {collapsed: false}).addTo(map);
        
        myPbfLayer.on('click', function(e) {
                    console.log(e);
                    });
</script>
</body>

</html>

This one vector layer will contain multiple objects, and often theese objects will overlap with each other.

I have added an onClick event listener to the vector layer, so that I can react to the user clicking on an element.

The problem: The event listener will only trigger for one of the objects (the topmost?), but I would need a way to get all objects that are located at the position that was clicked on.

This is an example event that will fire in such a case:

{layer: e, propagatedFrom: e, originalEvent: PointerEvent, containerPoint: x, layerPoint: x, …}
containerPoint
: 
x {x: 315, y: 309}
latlng
: 
M {lat: 51.83847369321496, lng: 11.928371503949167}
layer
: 
e {properties: {…}, _parts: Array(1), _initHooksCalled: true, _eventParents: {…}, _renderer: e, …}
layerPoint
: 
x {x: 620, y: 284}
originalEvent
: 
PointerEvent {isTrusted: true, pointerId: 1, width: 1, height: 1, pressure: 0, …}
propagatedFrom
: 
e {properties: {…}, _parts: Array(1), _initHooksCalled: true, _eventParents: {…}, _renderer: e, …}
sourceTarget
: 
e {properties: {…}, _parts: Array(1), _initHooksCalled: true, _eventParents: {…}, _renderer: e, …}
target
: 
e {_url: '[url removed]', options: {…}, _dataLayerNames: {…}, _initHooksCalled: true, _leaflet_id: 73, …}
type
: 
"click"
[[Prototype]]
: 
Object

Is this at all possible? Is there a way to either make an event fire for all objects under the mouse cursor instead of just the top one, or is there at least some hacky workaround to get all the objects located under the cursor? (presuming the vector pbf tiles are my only source for the objects)

1
  • @TomazicM I do not think that code will make my question better to understand or more easy to answer, but since the policy requires it, I have added my code. Thanks for giving me the hint! Jan 21 at 16:52

1 Answer 1

0

There is no out-of-the-box solution for this. Slight modification of plugin is required, specifically of L.Canvas.Tile renderer. This means that this renderer has to be used when creating layer with L.vectorGrid.protobuf.

Modification is done using .include method:

L.Canvas.Tile.include({
  _onClick: function (e) {
    var point = this._map.mouseEventToLayerPoint(e).subtract(this.getOffset()), layer, clickedLayer;
    var layers = [];

    for (var id in this._layers) {
      layer = this._layers[id];
      if (layer.options.interactive && layer._containsPoint(point) && !this._map._draggableMoved(layer)) {
        clickedLayer = layer;
        layers.push(layer);
      }
    }
    if (clickedLayer)  {
      e._layers = layers;
      L.DomEvent.fakeStop(e);
      this._fireEvent([clickedLayer], e);
    }
  }
});

This modification has to be included in the code anywhere before vector tile layer is created with L.vectorGrid.protobuf.

All clicked layers/features can then be retrieved like this:

myPbfLayer.on('click', function(e) {
  console.log(e.originalEvent._layers);
});

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.