Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS 15 Safari tab bar interrupts map interactions #11048

Closed
stephenheron opened this issue Sep 22, 2021 · 17 comments · Fixed by #11084
Closed

iOS 15 Safari tab bar interrupts map interactions #11048

stephenheron opened this issue Sep 22, 2021 · 17 comments · Fixed by #11084

Comments

@stephenheron
Copy link

stephenheron commented Sep 22, 2021

Maintainer's note: I'm prepending to the original issue a couple images to, I hope, most clearly illustrate the issue for people landing here, because there are two separate things going on. The first is the new iOS 15 Tab Bar, which toggles visibility even when a library like Mapbox attempts to call preventDefault on interaction events. This is iOS 15 behavior which cannot be changed:

image1

The second, which is the Mapbox GL JS behavior resolved in this issue, is that tab bar movement emits window resize and blur events which interrupt touch interactions. The above image contains the map in an iframe which prevents window resize events from reaching the map. When that is not the case, as shown in the image below, these resize events reach the map and halt interactions:

image3

The latter behavior is resolved by patches v2.5.1 and v1.13.2.

Some notes to help determine if your maps are affected by this issue:

  • Placing a map inside an iframe prevents resize and blur events from reaching the map inside. Such maps will not display this issue. (For example, the bug is not visible in the GL JS Examples, as they are inside iframes. If you want to view the issue, instead view the jsbin provided below on a device with iOS 15 Safari.
  • Maps pinned to the entire viewport with CSS do not display the issue, as the resulting page is not tall enough that the page can scroll, thus the tab bar is always visible and never toggles to hidden.
  • Maps instantiated with trackResize: false do not display the issue (this is probably very rare).

Original issue:

Hi,

We are seeing some funny behaviour in iOS 15 when attempting to move the map vertically. It seems when attempting to pan vertically it triggers the address bar in iOS 15 to show/hide and it stops the map pan. I have attached a a video showing the issue. This is from a simulator but we are also seeing the issue on real devices.

Screen.Recording.2021-09-22.at.20.22.34.mov

We are still debugging on this end so I am not 100% sure if it is a Mapbox issue or something we have done. Just flagging early in the hopes someone else may have seen something similar.

Thanks,
Stephen

@stephenheron
Copy link
Author

A wee update, I stripped back our site until it was basically just a a shell and it was still happening. I took that shell and popped it on a JSBin https://jsbin.com/tubitov/edit?html,output as it is still happening.

Strangely when I look at your example site (https://docs.mapbox.com/mapbox-gl-js/example/simple-map/) it doesn't seem to happen. The address bar appears/disappears but it doesn't result in the sort of hitching I get on my site and in the bin.

@rreusser
Copy link
Contributor

rreusser commented Sep 22, 2021

Unless I'm mistaken, I think this is the same issue. I don't know of a solution, but apparently it's a new "feature" and is awful for interactive apps.

https://twitter.com/cmiller__/status/1427849922649407495

Here's a page with some more info: https://www.cultofmac.com/750310/latest-ios-15-beta-lets-users-move-safari-address-bar-to-the-top-of-the-screen/

Just to be clear, iOS 15 is still in beta, right? It sounds like they're getting a lot of pushback on this and may be removing/modifying it.

@ryanhamley
Copy link
Contributor

I believe the address bar is still at the bottom by default, it's just no longer floating. That same Twitter thread shows that the unexpected UX is still happening. iOS 15 appears to be generally available as of September 20th. I see an option on my phone to upgrade to it.

@avpeery
Copy link
Contributor

avpeery commented Sep 22, 2021

Hi all, I upgraded my phone to iOS15 and can confirm that the address bar is at the bottom, and not floating or hiding. @ryanhamley the twitter comment appears to be from August 19th, before the release September 20th, so possible changes since then in regards to not have the address bar floating anymore.

@stephenheron, thanks so much for submitting this issue and including a jsbin. I tested out panning and scrolling on your jsbin with my iOS device after updating to iOS15 this afternoon, and have not yet reproduced this problem. Though it seems to be an iOS15 update-wide issue across different applications.

@stephenheron
Copy link
Author

stephenheron commented Sep 23, 2021

Hi @avpeery

Thanks for having a look! I just had a look at the link I sent you and I couldn't replicate it either which was strange. Until I looked at the jsbin directly (Not in edit mode and it happened).

Could you try this link: https://jsbin.com/tubitov/ and see if you can replicate?

I am also wondering if screen size has an effect, I am on an iPhone 12.

It would be okish if the bar just hide/showed but the real issue is that the pan/scroll on the map kinda stops when it happens.

Thanks,
Stephen

@rreusser
Copy link
Contributor

rreusser commented Sep 23, 2021

I'm seeing the same behavior in public iOS 15 on an iPhone 7. I modified Caleb Miller's codepen to add lots of stopPropagation and preventDefaults on touchstart, touchmove, touchend, and mousedown, but I'm still seeing the same issue. This is fairly surprising.

https://codepen.io/rsreusser/pen/RwgYjKV

Update: I can change the tab bar (bottom) to an address bar (top) in the settings, and then we're basically back to pre-iOS 15 behavior. But we of course can't count on users to have done that. This is starting to seem a bit like a can't fix issue unless there's a clever, yet-unknown-to-me event-handling trick which Apple set up to be able to get around this.

@leigeber
Copy link

leigeber commented Oct 3, 2021

In our version of this iOS 15 issue our map fills the viewport and the bottom placement isn't problematic but if you opt to have the bar up top then everything falls apart as you pan around with drawers constantly opening and closing. Seems like a fundamental issue with how Safari is propagating events from the Mapbox canvas.

Huge issue for us right now being a real estate application.

@stephenheron
Copy link
Author

@leigeber Yeah I just changed Safari to the top bar and it still feels very odd. Panning left/right even seems strange and sometimes it tries to take back a page.

@avpeery is there any progress on someone having a look at this? I had a look at the code but I can't really figure our what is going on.

@rreusser
Copy link
Contributor

rreusser commented Oct 4, 2021

@stephenheron I do now see the issue you're talking about in your codepen, in which the map stops panning. I think it didn't immediately register because the basic mapbox examples do not exhibit this issue. The only difference I can see is that the examples are in an iframe. Wrapping your example in an iframe does seem to work around the panning being halted, though it doesn't stop the address bar from hiding/showing.

Here's where I'm at on the issue:

  • The fact that it's impossible to prevent events from affecting the address bar seems like a significant bug on Apple's part. Here's a simple codepen that throws every prevent default, stop propagation, and pointer capture I can think of at the problem, with no effect: https://codepen.io/rsreusser/full/mdwYNNe
  • The fact that maps without an iframe halt when panned may be an apple bug in which events stop arriving, or it may be a Mapbox bug for some yet-unknown reason. I haven't gotten to the bottom of this yet. One workaround is to place the map in an iframe, though this is obviously not ideal.

We are indeed looking into this, and I'll keep this ticket updated with any new information we find.

@rreusser
Copy link
Contributor

rreusser commented Oct 4, 2021

Here's a small update:

For debugging, here's a simple page for demonstrating the interrupted-pan issue within the mapbox-gl-js repo:

debug/issue-11048.html
<!DOCTYPE html>
<html>
<head>
    <title>Mapbox GL JS debug page</title>
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <link rel='stylesheet' href='../dist/mapbox-gl.css' />
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>

<body>
<div style="min-height: 60vh"><div id="map" style="width: 300px; height: 300px"></div> <div>

Lucas ipsum dolor sit amet obi-wan skywalker solo jango jade grievous jango organa darth obi-wan. Tatooine gamorrean droid dantooine darth moff. Greedo leia darth maul jar r2-d2 jar secura hutt. Jabba mace cade palpatine. Ventress luke zabrak yoda lando organa mon hutt. Padmé skywalker calrissian moff. Antilles moff hoth moff jinn yavin maul. Hutt baba skywalker moff kenobi leia calrissian skywalker. Wookiee mothma binks boba ewok leia. Antilles palpatine jade jade jinn bespin sebulba. Kashyyyk yavin skywalker endor ackbar wedge calamari calamari cade.

Dagobah coruscant obi-wan moff ben kashyyyk antilles. C-3po yoda lars amidala mandalorians jabba antilles skywalker. Yoda dagobah amidala dantooine coruscant anakin. Utapau windu watto lando tatooine ben kenobi. Darth mandalore skywalker binks baba cade calrissian. Alderaan han maul anakin moff anakin. Vader naboo jinn moff aayla windu. Antilles secura ackbar hutt ackbar gonk. Organa moff jade skywalker r2-d2 wampa. Darth cade skywalker mandalore. Cade hutt maul calrissian. Tatooine jade organa yoda lando ackbar obi-wan coruscant obi-wan.

Dantooine solo owen coruscant moff windu organa moff. Wedge biggs coruscant hutt hutt lando mothma. Biggs solo lars secura dagobah. Jinn antilles tatooine jawa padmé skywalker antilles. Skywalker greedo jawa mon k-3po. Yoda mace lando c-3p0 sidious hutt mara chewbacca dagobah. Mon solo naboo yoda kamino wedge gonk. Ahsoka bothan calamari calrissian gamorrean. Baba kamino mace sith mon kit antilles. Jabba antilles yoda c-3po maul hutt solo. Antilles coruscant biggs darth skywalker. Boba skywalker wedge mustafar organa.

Mon mara luke fisto. Padmé grievous coruscant jango darth darth padmé hutt kessel. K-3po chewbacca k-3po moff cade tusken raider ahsoka palpatine. Moff vader moff jar bothan hutt. Obi-wan cade kenobi grievous skywalker hutt. Moff utapau kit darth owen wookiee kenobi jinn. Ben darth luuke ponda gamorrean hutt leia sebulba fett. Sidious organa twi'lek organa kessel. Tusken raider antilles boba jango dantooine. Binks antilles calrissian yavin mandalorians kessel ackbar. Hoth padmé antilles jango windu.

Fett yavin aayla lando amidala. Grievous darth palpatine darth. Skywalker skywalker biggs jawa windu antilles jabba moff mon. Dagobah moff windu bothan. Skywalker moff padmé fisto jango darth ventress mothma. Organa moff moff yavin alderaan. Skywalker calrissian skywalker mustafar skywalker twi'lek. Jawa sith calamari solo moff moff ackbar. Ben endor kessel aayla. Solo lando thrawn amidala dooku qui-gonn binks. Skywalker hutt yoda dooku obi-wan sidious grievous coruscant jango. Skywalker aayla moff solo ewok anakin yoda dagobah dooku.

<script src='../dist/mapbox-gl-dev.js'></script>
<script src='../debug/access_token_generated.js'></script>
<script>

var map = window.map = new mapboxgl.Map({
    container: 'map',
    zoom: 12.5,
    center: [-122.4194, 37.7749],
    style: 'mapbox://styles/mapbox/streets-v11',
    hash: true
});

</script>

</html>

The behavior I'm seeing is that, new in iOS 15, Safari fires some not-yet-determined event whenever the tab bar moves during hide/show. This event somehow invokes touchPanHandler.reset(), which then interrupts the pan, even though subsequent touchmove events are still received (and discarded).

This means the interrupted-pan issue can be fixed, but I don't have a cord available to be able to use the Safari debugger, making fully nailing this down much more difficult. The goal at this point seems to be to determine what's invoking touchPanHandler.reset().

@LowSociety
Copy link

LowSociety commented Oct 4, 2021

Isn't it simply the fact that iOS 15 now alters the height of the viewport regardless of whether the touch event triggers scrolling (ie even if it's preventDefault) thus triggering a resize event on the window? The resize event then probably triggers a reset which in turn stops the panning. You can simulate this on a desktop by triggering a fake resize event while panning, with the exact same behavior:

window.setInterval(function() {
    window.dispatchEvent(new Event("resize", {"bubbles":true, "cancelable":false}));
}, 5000);

@rreusser
Copy link
Contributor

rreusser commented Oct 4, 2021

@LowSociety You're exactly correct. trackResize is a map constructor option and defaults to true. If you set this to false, then the halting of panning should go away. If your map uses up the whole viewport and requires resizing on every window resize event, then things aren't quite as simple.

  • If your map is a fixed size on a page and doesn't need to be resized every time the window resizes, setting trackResize: false will fix the issue.
  • If your map needs to be resized when the window resizes, then it's not so simple. We're looking at caching the dimensions and more aggressively filtering resize events before they interrupt interactions. This would improve the situation.
  • If your map is fixed (or absolute) positioned to the whole viewport size, then it may actually change size so that caching dimensions wouldn't help anything (because they're actually changing). I don't yet know a solution for this case.

@LowSociety
Copy link

Thanks for the info @rreusser! As a workaround to other problems caused by this iOS update I've been deferring resize events to the end of user interaction. For example if the user is dragging something across the screen, I don't recalculate offsets on resize until after the user has stopped dragging. Of course, this only works if the calculations are not already inherently tied to the viewport size via something like css percentages/vh/vw but it makes me wonder if there really are times where a resize/reset needs to be triggered during panning? Isn't it essentially the equivalent of rotating your screen while panning the map, which already would cause a reset before the iOS update anyway?

@rreusser
Copy link
Contributor

rreusser commented Oct 4, 2021

Yup, I think that's just it, @LowSociety. All previous resize events were either mutually exclusive with map interactions (e.g. resizing the window with the mouse), or you had no reasonable expectation to continue the map interaction uninterrupted (e.g. rotating the device during panning). This is the first time in which resize events arrive during completely normal map interactions.

I suspect that we might be able to simply skip halting of interactions on resize. It's might produce jumpy interactions for completely contrived cases (like panning during device rotation), but it would perhaps solve this for more cases than filtering resize events.

@rreusser rreusser pinned this issue Oct 4, 2021
@rreusser rreusser changed the title iOS 15 Safari Pan/Scroll Issue iOS 15 Safari tab bar interrupts map interactions Oct 4, 2021
@rreusser
Copy link
Contributor

rreusser commented Oct 6, 2021

@stephenheron @LowSociety @leigeber We've published a patch version mapbox-gl@2.5.1 with a fix for this behavior. We'll be looking at which other versions to which to backport this change as well. Thanks for reporting and helping us get to the bottom of it!

@stephenheron
Copy link
Author

@rreusser Thanks to you and the team for looking at the issue and fixing it!

@LowSociety
Copy link

Awesome job @rreusser! Hopefully iOS changes the new behavior and goes back to changing the navigation bar height only on scroll, but this change covers both scenarios.

@asheemmamoowala asheemmamoowala unpinned this issue Dec 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants