I am trying to reduce the amount of permanent tooltip on my leaflet map for performance reasons. I have over 5000 geoJSON Polygons in my non-geographic map. At a specific zoom level, my Polygons should receive a label a.k.a Tooltip.
So my idea is to check each layer if it is in the current map bounds. But getting bounds and center LatLngs of over 5000 layers and checking if that layer is in the map bounds is time-consuming. If I add this in the map.moveend Event my map freeze. In addition, I have to fetch text for my labels from an SQLite Database.
Is there another solution for this problem?
EDIT:
My code so far:
var allLayer = L.geoJson(xhr.response, {style: style}).addTo(mymap);
var layerInCurrrentMapBounds = [];
mymap.on('moveend', function(e) {
if (mymap.getZoom() >= 5) {
allLayer.eachLayer(function(layer) {
var bounds = layer.getBounds();
if (bounds.isValid()) {
var latLng = bounds.getCenter();
if (mymap.getBounds().contains(latLng)) {
layerInCurrrentMapBounds.push(layer);
}
}
});
layerInCurrrentMapBounds.eachLayer(function(layer) {
layer.bindTooltip("test", {
permanent: true,
className: "my-label",
offset: [0, 0]
});
});
}
});
On the next moveend I have to remove all tooltips. In addition, I have to fetch my tooltip text from a sqlite database. And what if the user starts to drag the map rapidly. Could I make my function async and cancel this every time the user starts to drag again?
Best Answer
Solution 1 (see optimized solution 2 below after this one):
On possible solution would be to use very efficient Turf.js library for geospatial operations when checking if feature is visible in current view.
Example below creates 5000 GeoJSON polygons and displays them on the map, with permanent tooltips for polygons that are visible when zoom level is 12 or more. When map is panned or zoomed, tooltips are created for newly shown polygons and removed for those that are no more visible. Working JSFiddle is available here: https://jsfiddle.net/TomazicM/k4erLnf1/
When creating random polygons each on is given unique id. Then id is then used when creating
layersById
object which serves as a link between Leaflet layers/features and corresponding GeoJSON features/polygons when analyzing which GeoJSON polygons are visible in the current map view.This is the code:
Solution 2 (much quicker): Based on solution 1 as far as Turf.js library is concerned, this solution is using
Leaflet.VectorGrid
plugin for much quicker rendering of big GeoJSON layer. Since plugin does not support adding tooltips to features/layers, dummy (empty)L.divIcon
markers are created as placeholders for tooltips. Working JSFiddle is available here: https://jsfiddle.net/TomazicM/g5pwd3mk/This is the main part of the code: