mapbox-gl-js
mapbox-gl-js copied to clipboard
Icons disappear at certain zoom levels in Safari only, but are still clickable
Hi,
I am having a very strange Safari issue. On zooming in and out some of our pins that are drawn using a symbol layer appear and disappear.
https://user-images.githubusercontent.com/142855/134563726-870a36c0-4849-4562-bd06-c1e653d3f6e1.mov
It is not shown in the video but when the pins are not visible they are still clickable. I have checked in both Chrome and Firefox and the problem does not happen.
I have tried v2.4, v2.3 and v.2.2 and the problem appears in all of them. I also checked out main and the problem is also present. Strangely I did find a single commit where the issue is not a problem, the video below shows that commit in action 457f808ad2ecdb90b2c2f5511734f1a2f0790740
https://user-images.githubusercontent.com/142855/134564184-afe86510-4b9f-4094-aad7-8a9c25797123.mov
I understand this is a very strange problem so if I can provide any more debugging assistance I will do my best.
Thanks, Stephen
Hi @stephenheron it is an expected behavior for markers not render at certain zoom levels when using large geojson sources. You can check out the documentation here on different options when working with geojson sources. I also recommend trying to set 'icon-allow-overlap' to true in the symbol layer. Here is more documentation about the symbol layer if it helps as well. I will close this issue since it is not a bug report or feature request. If you need further assistance with this issue, please contact Mapbox Support. Thanks!
It is not shown in the video but when the pins are not visible they are still clickable. I have checked in both Chrome and Firefox and the problem does not happen.
Hi @stephenheron, closely re-read the section emphasizing that these icons are still clickable and it is not occurring in Chrome and Firefox. Can you include a minimal reproduction of the code in jsbin or codepen? Thanks!
Hi @avpeery
We had a look at replicating the issue in the jsbin and we discovered the source of the problems.
In our code we do something like this:
//This is a workaround until this issue gets looked at: https://github.com/mapbox/mapbox-gl-js/issues/9018
map.addImage(imageId, {width: 0, height: 0, data: new Uint8Array()});
map.loadImage(imageURL, (error, image) => {
if (!error) {
map.removeImage(imageId);
map.addImage(imageId, image);
}
});
};
It effectively sets an empty image and then loads in a real image. This is so we don't need to preload all our pin images. This issue (https://github.com/mapbox/mapbox-gl-js/issues/9018) talks about the need to be able asynchronously load images but that feature is not available so we did the above as a work around.
However this seems to be the source of our "disappearing" pins. It seems like quickly removing/adding the images results in some of the pins keeping the old image and some the new image.
To more easily visualise the issue we changed the invisible pins to instead be a gradient.
You can see this behaviour on this jsbin: https://output.jsbin.com/yolusir/22/
This is the core of the issue on the jsbin below:
const loadImage = () => {
const imageId = "poi-accommodation"
map.addImage(imageId, { width: 64, height: 64, data: getGradientImage() });
map.loadImage("https://placekitten.com/g/90/111", (error, image) => {
if (!error) {
const runSetTimeout = false;
map.removeImage(imageId);
if (runSetTimeout) {
setTimeout(() => {
map.addImage(imageId, image);
}, 1000)
} else {
map.addImage(imageId, image);
}
}
});
}
If we add a large setTimeout of 1s then it seems to be better however this is not a great user experience. You can see this behaviour here: https://jsbin.com/yolusir/25/
I hope this helps narrow down the problem! It does seem like a complicated one that is around add/removing of images. We did find this other issue: https://github.com/mapbox/mapbox-gl-js/issues/9004 which is sort of similar and talks about adding/removing of images.
Thanks, Stephen
I also built a version of mapbox-gl with the commit that I found that works (https://github.com/mapbox/mapbox-gl-js/commit/457f808ad2ecdb90b2c2f5511734f1a2f0790740) and it seems totally fine: https://output.jsbin.com/yolusir/27/
Thanks for your work investigating this @stephenheron! I'm looking into a fix for this, in the meantime a workaround is to replace the calls to map.removeImage()
and map.addImage()
with map.updateImage()
followed by map.triggerRepaint()
.
Here's an updated jsbin with the workaround. Let me know if that helps!
Another workaround that should be simpler for most use cases: load images on 'style.load'
instead of 'styleimagemissing'
events. ('load'
events also work but may be slightly slower.)
After further investigating this, I can confirm that this is the same as https://github.com/mapbox/mapbox-gl-js/issues/8335.
@stephenheron Can you confirm which (if either) of the above workarounds works for you?
If neither of the above work, there's a more general workaround shared in this comment.
Unfortunately, calls to addImage
currently require a restart to tile parsing, so addImage
called after loading an image will negatively affect map load time. I'm looking to move forward with asynchronous image loading (https://github.com/mapbox/mapbox-gl-js/issues/9018) to address the general problem, but please let us know if the workarounds are helpful in your use case!