maplibre-gl-js
maplibre-gl-js copied to clipboard
panTo is confused if map was hidden
DEMO:
https://maplibre.org/maplibre-gl-js/docs/examples/change-case-of-labels.html
(run in developer tools)
var div = document.querySelector('#map')
center = map.getCenter();
div.style.display = 'none';
setTimeout(function(){
div.style.display = 'block';
map.panTo(center);
}, 1000);
Use case: Let's say I have some location listing, when the user clicks on it I want to show a full screen map and pan to that location. There is a button to hide the map and return back to the page.
Right now panTo is not working correctly if the map was hidden (also there are some animation effects even if you just toggle the display of the div and nothing changed, but that's not really a problem)
It might be a resizing race condition or something similar, I would recommend the following (after setting display block, wait a few milliseconds):
let div = document.querySelector('#map')
let center = map.getCenter();
center.lat += 0.1;
center.lng += 0.1;
div.style.display = 'none';
setTimeout(() =>{
div.style.display = 'block';
setTimeout(() => {
map.panTo(center);
}, 500);
}, 1000);
The code that you have added moves the map to the current map's center, that means that panTo doesn't move the map at all. So I would recommend checking your code first, as with and without the timeout after the display block line the panTo works for me when tested. If the above still doesn't work, please provide better steps to reproduce, preferably a codepen/jsbin/stackblitz and also a video of the issue.
Yes the timeout hack is cute, but should not really be needed.
The center demo is just a demo, I know it should not move, but it is also a valid use case, user might click on the same location to see it again on the map.
Video:
https://github.com/maplibre/maplibre-gl-js/assets/3125689/22d72253-261a-4f9b-b93e-88a80684243e
I'm not sure the expected behavior is that it should work immediately when switching from display none
to display block
is the right expectation.
There are all kind of animation, resize events and other things in motion.
In any case, if the timeout workaround isn't a good solution, you are free to dig into what happens when the browser switches from none
to block
and propose a change in the code.
I'll be happy to review it :-)
It's also worth mentioning that canvas height is 300px and width is 400px when the map is hidden:
See here:
I've added the following code to see the behavior:
map.on("render", () => {console.log(window.getComputedStyle(map.getCanvas()).width)})
And when using panTo just after display block the width and height of the map are still those "default" ones.
I'm not sure I know why these defaults are set, maybe you can change them to 100vw/h
respectively and see if it solves the issue.
Overriding the canvas size (via css important, maybe internally it is still calculated incorrectly) didn't seem to have an affect.
I think a better workaround is instead of hiding the div, moving it to say z-index: -10;
seems to bypass the issue.
If the problem is indeed resize events, one could add 'map_is_panning' flag and not process them, but then it is unclear what should happen if map is panning and user resizes the window (or changes phone orientation etc). [probably recalculate destination again]
or, since in this case there is no real resize event, just check for that.