Anna Kleiner
Anna Kleiner

Reputation: 185

using map event handler for dynamically imported data massively slows down the page

I have a leaflet map with a few hundred markers on it. The markers are clustered with the markercluster plugin, and the data for the markers is loaded with a dynamic import depending on the user’s language.

These markers get filtered by tags and a search field (that works), and I want them to also be filtered by what part of the map is currently in view (I’m outputting a list of all the results in HTML). To this end I have a function updateFiltering(points) that takes an array of markers as a parameter.

I want to call this function whenever the map is done moving, whether that’s from panning or zooming. I’m doing it like this:

let sth = 
  import('./data-'+lang+'.js')
    .then((langdata) => {
      updateCheckboxStates();
      addMarkers(pFilter(langdata.points));
      updateFiltering(langdata.points);
      const points = langdata.points;

      map.on('moveend', function(e) {
        updateFiltering(points);
      });
    })
    .catch((error) => {
      console.error(error);
    });

This works, but after a bit of zooming around it slows the page down immensely, to the point where the browser prompts me to stop the script. The console said ‘too much recursion’ at one point – that explains the massive delay, but I don’t understand why that’s happening?

If I use an event on the markercluster layer, for example

      markers.on('animationend', function(e) {
        updateFiltering(points);
      });

– this works alright (but doesn’t catch all the use cases). But any event handler attached to map slows the page down.

I’m really grateful for any advice!

Upvotes: 0

Views: 41

Answers (2)

Anna Kleiner
Anna Kleiner

Reputation: 185

Okay so, I cannot say exactly what the problem was. But I took a good hard look at all of my filtering functions and they did seem a little convoluted to me. What might have been problematic is that MarkerCluster apparently filters out everything outside of the current map view, and I was also doing that.

I ended up adding another plugin, Leaflet.FeatureGroup.SubGroup, which I am now using to filter by categories. And for the list output in the HTML I loop through all markers currently visible and remove the hidden class from the entries with the corresponding ids.

I also have a text input for filtering which originally prompted my more convoluted approach. Now I am doing it with another loop through the visible markers, hiding the ones that don’t match. This is definitely visible when moving or zooming the map, but it only takes half a second or so for some of the newly appearing markers to disappear again, and all the transitions are super smooth, so I think this is acceptable.

Thanks for your input everyone!

Upvotes: 0

Vashishtha Srivastava
Vashishtha Srivastava

Reputation: 120

Function call should be on map event only. But the catch is, you should not call the function until a specific amount of zoom has been done.

map.on('moveend', (e) => {
    if (zoom > previosScreenRation * 1.3) {
        updateFiltering(points);
    }
});

This code actually works, when the current zoom percentage crosses the previous screen ratio by 30 Percent. This will help you with your problem of javascript slowing down page. Its the same concept when we are having an infinite list in a web page, and upon scrolling down to 80 percent of page length, we trigger another api call to fill the page list, thereby increasing the now total length of page

Upvotes: 0

Related Questions