maplibre / maplibre-gl-js

MapLibre GL JS - Interactive vector tile maps in the browser
https://maplibre.org/maplibre-gl-js/docs/
Other
6.69k stars 717 forks source link

Multiple queued renders in response to changing styles #4765

Open tomhicks opened 1 month ago

tomhicks commented 1 month ago

maplibre-gl-js version: 4.7.x

browser: All

Steps to Trigger Behavior

  1. Have a complex map with lots to render
  2. Set the style rapidly, such as in response to a hover
  3. Renders are queued up, sequentially rendering old states through to the new one

Link to Demonstration

Sorry that this is the complete opposite of a minimal reproduction, however it's the best way I know to make a complex enough map.

https://felt.com/map/Untitled-Map-3W49ADnfJTKyOC9AHrmlO9BSB?loc=51.472,7.718,6.74z

If you run your mouse rapidly over the very dense cycle network of the Netherlands and Germany, you can see our highlighting in pink plays catchup, sometimes over a number of seconds, leaving a trail of pink highlights.

I know that we should probably be using feature state for highlights, but there are other cases that we have avoided surfacing in our production app where this happens when rapidly changing styles in other ways.

Expected Behavior

I would expect the renders not to be queued up and if it's lagging to only render the latest state, or something.

I have tried to implement this in user-land by doing something like only setting the next style once a "render" event has been received, but that doesn't seem to help. I have a feeling that this might be something cascading being triggered from within the render callback itself. I also note that there seems to be a cancellation mechanism in the render queuing, but I've been unsuccessful in trying to hack that so far.

Actual Behavior

The map queues up a series of renders/draws, leaving a "trail" of old states being shown on screen.

HarelM commented 1 month ago

The issue can be seen from the above link, but it is not clear what you did to cause this issue, much like posting a video of this issue, I guess. I would recommend rechecking your code to see what can be done to solve this better. I'm not sure the solution should be to drop render requests, but it's hard to give a good advice without really understanding the issue at hand. I would still recommend trying to create a minimal reproduction.

tomhicks commented 1 month ago

I will see if I can come up with a minimal repro. In the meantime, you can access the map instance at window.felt.mapLibreMap if that would allow you to inspect the state, or at least you can perhaps advise me how to minimally reproduce based on that. (e.g. is there a way to export the user-controlled state of a map in order to reimport for debugging?)

In case this helps:

HarelM commented 1 month ago

setStyle is a heave method to call every frame, you can use setPaintProperty or setLayoutProperty which might perform better. I don't have a way to export data in order to debug... Feel free to continue digging into this.