If you open Google Maps in Chrome/Firefox on a laptop with a trackpad, if you pinch-zoom, it just zooms the map, and the floating UI elements remain static. So I know what I am trying to do is possible.
It seems the browser doesn't emit touch*
events for trackpad touches on desktop browsers, but it does emit a series of wheel
events (with event.ctrlKey
set to true
) for a trackpad pinch-zoom gesture.
The problem is, even with event.preventDefault()
, the browser still always zooms the whole page. It seems that calling preventDefault()
on a wheel
event just prints this warning in the console (Chrome 92):
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312`
(The URL in the warning doesn't seem to be any use.)
I tried using same the meta viewport tag as Google Maps (<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
) but it doesn't help.
So how does Google Maps do it? How do they prevent the default behaviour (zooming the whole page) when you pinch-zoom on the trackpad?
Tip: On your touchscreen, you can touch and hold an area with 2 fingers, and then pinch open to zoom in, or pinch close to zoom out.
Pinch to zoom in on content: In full screen mode, touch the video with two fingers. Move your fingers away from one another, while touching the video screen. Once you let go, the video will play at the new zoom level.
ctrl + mousewheel will then control the pinch zoom instead of the regular zoom.
Tap anywhere on the screen, except the keyboard or navigation bar. Drag 2 fingers to move around the screen. Pinch with 2 fingers to adjust zoom. To stop magnification, use your magnification shortcut again.
I don't have a trackpad at hand, but since you said that wheel
events were emmited, I assume the context is the same by using a mouse's wheel.
Calling addEventListener()
with {passive: false}
as its third argument will do it.
Namely:
window.addEventListener('wheel', function(e) {
e.preventDefault()
...
}, {passive: false})
In addEventListener()
's document, the description of the passive
option states that:
A boolean value that, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning.
And according to the section titled "Improving scrolling performance with passive listeners" in the same page:
According to the specification, the default value for the passive option is always false. However, this introduces the potential for event listeners handling certain touch events (among others) to block the browser's main thread while it is attempting to handle scrolling, resulting in possibly enormous reduction in performance during scroll handling.
To prevent this problem, some browsers (specifically, Chrome and Firefox) have changed the default value of the passive option to true for the touchstart and touchmove events on the document-level nodes Window, Document, and Document.body. This prevents the event listener from being called, so it can't block page rendering while the user is scrolling.
Although the paragraph above only mentions touchstart
and touchmove
events, I found that it is also applied to the wheel
event in Chrome and Firefox.
So if you want to make preventDefault()
work, you have to specifically set the passive
option to false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With