maplibre-gl-js
maplibre-gl-js copied to clipboard
Lagging when zooming in/out of the map (especially with free rolling mouse wheel)
maplibre-gl-js version: v4.5.0
browser: Chromium (Version 126.0.6478.126 (Official Build) (64-bit)) and their derivatives
Steps to Trigger Behavior
- Go to https://maplibre.org/maplibre-gl-js/docs/ in a Chromium (or derivative) browser
- Zoom in/out fast and you can see that it lags (especially noticable using a mouse with free rolling wheel (like mx master 3) )
Link to Demonstration
Laggy Chromium:
https://github.com/maplibre/maplibre-gl-js/assets/16204269/62e4ec0a-08e7-44ee-bec0-91e137971e0f
Smooth Firefox:
https://github.com/maplibre/maplibre-gl-js/assets/16204269/3848aa28-bce4-414f-a7dd-70caeed950e0
Expected Behavior
For smooth zooming to be the same as in Firefox browser
Actual Behavior
Lagging when zooming in Chromium
I doubt there's a (easy) solution to this issue. You are welcome to investigate though.
This is what I have so far:
- the lag does not occur when DevTools are open in Chromium (interesting!)
- after adding a throttle function of 20ms on the HandlerManager.handleEvent function call the lag went away and the zooming was smooth (my screen is 60 FPS so throttle of anything higher than 17ms removes the lag)
Next I will investigate if there are more renders happening during a single frame received from requestAnimationFrame
The cause of the lag is an issue in the easing functionality in the scroll_zoom.ts. Will investigate further.
Figured it out!
https://github.com/maplibre/maplibre-gl-js/blob/0327486058079000767bac9e30111c84909c225a/src/ui/handler/scroll_zoom.ts#L293-L302
When the mouse scroll wheel is rotating fast the value of t is 0 which causes the easing function to return the same result, hence why the zooming stops. Eventually the value of t becomes >0 which causes the zoom level to change suddenly but then again it stops when t becomes 0 and that is the cause of the lag.
The fix that I found is the following:
let t = Math.min((browser.now() - this._lastWheelEventTime) / 200, 1);
if (startZoom !== targetZoom && t === 0) {
t = 0.1;
}
Number 0.1 seems to be a sweet spot for smooth zooming.
This only affects fast wheel rotation so no other zoom methods nor regular (stepped) wheel rotation is affected.
I will prepare a PR with this fix. Pinging @anandthakker as he wrote the original code.
Why is it 0? last wheel and browser.now are the same?
Yes, they are the same.
https://pastebin.com/KjKB68Nv
This is the log of me spinning the mouse wheel. You can see that most of the time the difference is 0. When I slow the wheel down at the end we can see the diff increase.
Feel free to open a PR, I'll be happy to review it. Thanks for taking the time to investigate this!
Apologies for commenting on a closed issue, but I am still experiencing this issue in Chromium based browsers; zooming in and out using the mouse scroll wheel feels super choppy, unless the developer tools are open (this behavior is noted above in here, hence I believe it must point to the same issue). It appears that v4.5.1 did include the fix relating to this bug (hence the issue is closed and marked as completed), so I am not sure how/why it persists on my end. I have tested this on v4.5.1 locally and in production for personal projects and the bug is present in all.
Here is a replication of the original example above from https://maplibre.org/maplibre-gl-js/docs/:
- Firefox (no issues):
https://github.com/user-attachments/assets/805152ac-ef90-415c-849f-7ae14deb49f6
- Chrome (laggy):
https://github.com/user-attachments/assets/04a8c746-981b-447c-8b7d-ec9d15cd2207
- Chrome (no issues, developer console open):
https://github.com/user-attachments/assets/8334dd3f-97c4-43bb-8f3b-ac0830a987f0
Is there any chance that the fix above was not wholly implemented and/or included in the latest NPM version properly?
The PR was merged on Jul 1. The release of 4.5.1 was done on Aug 1. It might be that you have a cached version and thus the fix is only visible when the dev tools are open? In any case, please let me know if you need me to reopen this issue.
My mouse scroll gets recognized as a trackpad more often than not when using stepped scroll (mx master 3, magnetic stoppers) so testing is a bit tricky (and I don't have a mouse with regular scroll wheel).
This sentence from PR #4366 is relevant, as I am also using an MX Master 3 mouse with stepped scroll on – using a regular mouse does not exhibit this laggy behavior. That said, Firefox and Safari do not have this lagginess when using an MX Master 3, but Chrome does; would this be a Chromium issue rather than a maplibre one?
Sounds like a Chrome issue to me...
Same here, but still unclear as to why having the dev tools open fixes the issue on Chrome...
@firatciftci have you managed to solve the issue? I also see stuttering when zooming on latest 4.5.2 version.
Moreover, when I downgrade to 4.5.0, it's gone.
Here is a smooth scroll: https://github.com/user-attachments/assets/33d1df10-0553-40ef-ad02-8f6dd52020bb
And here are some random zoom jumps on latest version: https://github.com/user-attachments/assets/579a5a44-a1eb-4866-9485-8d0fda4e7925
@Monstrofil I haven't had the time to look more into it yet – are you also using an MX Master 3?
I can confirm that reverting back to 4.5.0 fixes the issue. @HarelM, as counterintuitive as it may sound, it might make more sense to revert the 'fixes' in PR #4366 – the changes in src/ui/handler/scroll_zoom.ts seem like a real regression in scroll zooming for certain mouse types. It might make sense to re-open this issue, and I will get to work on filing a new PR to see what I can do to address this once-and-for-all.
Feel free to submit a PR that reverts this fix.
@Monstrofil I haven't had the time to look more into it yet – are you also using an MX Master 3?
No, just a generic A4tech mouse.
I'm experiencing the same issue on chrome with a Logitech G403
I am also having the same issue on version 4.7.1,
Lagging when scrolling with mouse on chrome, especially on higher zoom levels (>8). Issue is resolved when dev tools are open. The issue is similar on firefox. Although it seem that the scrolling is faster on firefox, it still has some lag.
Interestingly the built it map.zoomIn() and map.zoomOut() work just fine, and work consistently across browsers. Maybe they can be used to fix the issue.
I make a custom scroll method implementation that works better for me than the default one, also it works across browsers. Its not as butter smooth as google maps but hey if anyone has any ides how to improve it met me know
`
let wheelLastTime = 0;
map.scrollZoom.disable();
map.on('wheel', function (wheelEvent) {
const mouseEvent = wheelEvent.originalEvent;
const mapContainer = map.getContainer();
const offsetX = mouseEvent.clientX - mapContainer.clientWidth / 2;
const offsetY = mouseEvent.clientY - mapContainer.clientHeight / 2;
const zoomDelta = mouseEvent.deltaY / -400;
const zoom = map.getZoom() + zoomDelta;
const wheelTime = Date.now();
const wheelElapsed = 1 + wheelTime - wheelLastTime;
const wheelFactor = Math.max(1, Math.round(100 / wheelElapsed));
wheelLastTime = wheelTime;
const duration = 200 / wheelFactor;
console.log(duration, wheelFactor);
map.zoomTo(zoom, {
offset: [offsetX, offsetY],
duration: duration
});
});`
Same issue here with 4.7.1. Reverting to 4.5.0 fixes it. macOS on a M1 mac, Chrome, Logitech G Pro X Superlight (non-free rolling). The issue is immediately noticeable, it's not required to scroll unreasonably fast.
I'm not experiencing any of these issues, but if you think the latest fix should be reverted I suggest to make sure the original issue that was reported does not return.
I've also been experiencing these same issues with mouse scroll not being smooth since 4.5.1.
I believe I have identified the issue, and can reliably reproduce on chrome and Firefox using a regular mouse wheel. I've tried 3 different mouses with regular stepped scroll wheels and they all trigger this issue. The issue frequently occurs when a 2nd scroll event happens immediately after the previous has finished. This happens on quick mouse scroll into or out of a map with multiple scroll wheel actions, and is also easily triggered if the stepped mouse wheel is scrolled beyond it's bump.
When this 2nd scroll event occurs, 'browser.now()' and _'this.lastWheelEventTime' are often the same value. In this case, 'lastWheelEventTimeDiff' gets set to 0 on line 307 of scroll_zoom.ts. Then, immediately after on line 308, 'lastWheelEventTimeDiff' is falsy and the easing block is skipped, and 'zoom' is immediately set to 'targetZoom' on line 321, causing the immediate jump in zoom level and stuttering affect.
https://github.com/maplibre/maplibre-gl-js/blob/87486a5ef2085e600e8fa4e31252629dd8488dcd/src/ui/handler/scroll_zoom.ts#L307-L323
Removing the 'lastWheelEventTimeDiff' check resolves the issue, but would re-introduce the original problem for free rolling mouse wheels. ~~I think setting 't' to a minimum value for 1ms time difference when time difference is 0 would address the original issue for free scrolling mouse wheels (This is very similar to the original fast scroll fix proposed by @Codebreaker101 at the top of this page). However, I cannot test as I don't have this type of mouse.~~ [EDIT - It doesn't!]
Please read through the this thread and the relevant PR. The original fix was using 0.1 as minimum time to solve this, but I'm not sure why the solution was changed, maybe because of problem testing the code. See here:
- #4366
@Codebreaker101 can you help out here to resolve this?
I've now got a free scrolling mouse and have been working on this. I have a fix which reverts back to 4.5.0 behavior and also addresses the free rolling wheel issue. In Chrome it's now very smooth regardless of mouse type / scroll speed. I'd say the fast scroll zoom performance between Firefox and Chrome is now about the same.
https://github.com/user-attachments/assets/cd02b577-257f-4654-b17a-c4ad66c5e4d1
I need to look into writing test(s) and then I would like to submit a PR for review please? @HarelM
Sure, I'll be happy to review a proper fix to this issue, thanks for looking into it!