mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.2k stars 2.22k forks source link

map.on() and passive: false events #6679

Open hyperknot opened 6 years ago

hyperknot commented 6 years ago

mapbox-gl-js version: 0.45.0 browser: iOS 11.3

Steps to Trigger Behavior

  1. create a map with touchZoomRotate: false
  2. add an event handler to a passive: false event, like touchmove which calls e.preventDefault()
  3. try touch-zooming, the browser viewport will zoom

Link to Demonstration

full screen: https://03qo50z3rw.codesandbox.io/ https://codesandbox.io/s/03qo50z3rw

Expected Behavior

e.preventDefault() should disable browser viewport zooming

Actual Behavior

The browser window zooms, even with e.preventDefault()

I tried an alternative, e.originalEvent.preventDefault() which seems to work, however the official drag point example uses e.preventDefault().

cc: @jfirebaugh ref: https://github.com/mapbox/mapbox-gl-js/issues/6095 pr: https://github.com/mapbox/mapbox-gl-js/pull/6248

jfirebaugh commented 6 years ago

This seems like expected behavior to me. The documentation for preventDefault says:

Prevents subsequent default processing of the event by the map. Calling this method will prevent the following default map behaviors:

  • On touchstart events, the behavior of DragPanHandler
  • On touchstart events, the behavior of TouchZoomRotateHandler

So if TouchZoomRotateHandler is disabled, there's nothing for preventDefault to do on pinch gestures.

Can you say more about what you're trying to accomplish?

hyperknot commented 6 years ago

I'm trying to implement dragging of a feature like in the official drag point example. My problem is that if the user accidentally does a pinch instead of a drag the viewport will zoom with no way to go back.

My best idea so far is to check for originalEvent.scale!=1 and do an originalEvent.preventDefault, but even this can sometimes zoom the UI.

I'll create an example showing this behavior.

On 2018. May 16., Wed at 17:22, John Firebaugh notifications@github.com wrote:

This seems like expected behavior to me. The documentation for preventDefault says:

Prevents subsequent default processing of the event by the map. Calling this method will prevent the following default map behaviors:

  • On touchstart events, the behavior of DragPanHandler
  • On touchstart events, the behavior of TouchZoomRotateHandler

So if TouchZoomRotateHandler is disabled, there's nothing for preventDefault to do on pinch gestures.

Can you say more about what you're trying to accomplish?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mapbox/mapbox-gl-js/issues/6679#issuecomment-389558901, or mute the thread https://github.com/notifications/unsubscribe-auth/AAeKj0vY0bacFyV9rpIDbng8b_zueFlKks5tzEQpgaJpZM4UBUO3 .

jfirebaugh commented 6 years ago

Do you want TouchZoomRotateHandler disabled all the time, or is disabling that just something you tried to suppress the viewport scaling?

hyperknot commented 6 years ago

Yes, the example I've given was just something I created for debugging. I'd like to disable touch zooming only while I'm grabbing a point.

Here are the real issues I've run into while setting up events like in "drag-a-point" example:

  1. The dragging is actually not following the touch point. You move it up and it goes 70% up. https://zw1n04ow14.codesandbox.io/ https://codesandbox.io/s/zw1n04ow14

  2. The touch zoom can "escape" the container sometimes. It happens both with touch zoom enabled when dragging a point, or with touch zoom disabled and manually doing preventDefault. I'm trying to create a reproducible case for this one.

hyperknot commented 6 years ago

OK, I managed to reproduce the "container escape" bug for touch to zoom. Just try to touch zoom the map in many different directions on an iOS device. https://jsbin.com/keguga/10

  1. Sometimes the touch events are caught and prevented. (scale = 1.x, defaultPrevented = true)
  2. Sometimes they are not. When they are not, they are still visible in the console (via Safari's iPhone debugging), and they have scale = 1.x, defaultPrevented = false.

Once the zoom "escaped" the UI is destroyed as there is no way to get back to the original viewport. Silly iOS Safari remembers the viewport even after a page reload. (If you go into the URL bar and press return it'll reset the viewport, but users will probably just press the reload button).

hyperknot commented 6 years ago

To trigger the buggy state, try touch zooming around the bottom UI elements, like the i button or the Mapbox logo.