4

I’m trying to leaflet to render about 30K points with their names. The text label should avoid overlapping, and important points should always be rendered firstly.

My strategy is:

  1. Use tippecanoe to make mbtiles file from geojson. (To make sure important points be rendered firstly, I have specified tippecanoe's minzoom and maxzoom for each point. )
  2. Use tileserver-gl to serve vector tile.
  3. Use VectorGrid plugin to render the vector tiles in leaflet.

I trying to use maputnik to make a style.json file, which seems very nice dealing with text label overlapping. However, I sadly find out leaflet VectorGrid plugin does not support style.json file. https://github.com/Leaflet/Leaflet.VectorGrid/issues/196

Now I'm stuck. What is my alternative to rendering those points with names?

8
  • Whats wrong with vector grid styling: leaflet.github.io/Leaflet.VectorGrid/…?
    – TomazicM
    Commented Aug 2, 2021 at 16:57
  • Have a look also at Leaflet.VectorTileLayer plugin, which is built on top of Leaflet.VectorGrid.
    – TomazicM
    Commented Aug 2, 2021 at 17:06
  • @TomazicM. I couldn't find out how to add textual properties in VectorGrids styling. github.com/Leaflet/Leaflet.VectorGrid/issues/67
    – J Law
    Commented Aug 2, 2021 at 21:12
  • 1
    Ah, now I understand. I once tried to deal with the same problem. Found a bit hacked solution that worked for my needs. It's based on the idea to create text part of features as tooltips dynamically only for the visible features. You can have a look at working JSFiddle here: jsfiddle.net/TomazicM/2o9z53u6. Here 15.000 random points are created and tooltips showed only for zoom levels over 10. Display logic can of course be adjusted to reflect some feature properties. You might get some idea from this.
    – TomazicM
    Commented Aug 3, 2021 at 8:49
  • @TomazicM Thank you very much for the inspiration. I came out with a workaround using getFeatureId option of vectorGrid. leaflet.github.io/Leaflet.VectorGrid/…. For each point, I make it into divIcon with their text properties, then add it to collisionLayer to avoid overlapping. github.com/MazeMap/Leaflet.LayerGroup.Collision Very clumsy, but doable.
    – J Law
    Commented Aug 3, 2021 at 15:26

1 Answer 1

4

Thanks for the inspiration from @TomazicM, I came up with this workaround with getFeatureId option of vectorGrid and leaflet layerGroup.collision plugin.

Firstly, add coordinates as properties for each point before making mbtiles file.

For each point render by tileserver-gl, using getFeatureId to get each point's coordinates and name properties, then make it to divIcon. Add each divIcon as marker to collisionLayer to avoid overlapping. github.com/MazeMap/Leaflet.LayerGroup.Collision

Finally, set style to transparent for the default rendering by VectorGrid.

My code is something like this, very clumsy, but doable. Please let me you if you have other solution.

 const vectorTileOptions = {
  getFeatureId: function (e) {
    const latlngs = [e.properties.lat, e.properties.lng];
    const stationName = e.properties.name;
    const marker = L.marker(latlngs, {
      icon: L.divIcon({
        html: `<img src=${redpointIcon} height="10" width="10" ><span class=labelName>${stationName}</span>`,
        iconAnchor: [5, 10],
      }),
    });
    collisionLayer.addLayer(marker);
  },
  vectorTileLayerStyles: {
    point: { color: "transparent" },
  },
};
L.vectorGrid.protobuf("http://[::]:8080/data/point/{z}/{x}/{y}.pbf", vectorTileOptions).addTo(map);
collisionLayer.addTo(map);

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.