👈 back to kenneth.io

Detecting multi-touch trackpad gestures in JavaScript

April 2018

Photo by [Scott Webb](https://unsplash.com/photos/ZLeogVvtXk0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/kP0pjdyYNyU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) Photo by Scott Webb on Unsplash

For a long time I have wondered how Google Maps and Figma have been able to support pinch-to-zoom multi-touch gestures from my trackpad on my Macbook, when there’s no special trackpad JavaScript events exposed.

So I started exploring this a few months ago and this weekend I stumbled upon this bug, 1052253 — OS X: Pinch to zoom gesture should map to mousewheel with the control key, like Chrome, in the Mozilla bug tracker and that finally made things click.

Apparently Microsoft with IE10 was the pioneers here, as they enabled pinch-to-zoom gestures from multi-touch trackpad’s to be surfaced as mousewheelevent with the ctrlmodifier set to true.

The Chrome team had a discussion about this back in January 2014, and the adaption landed in Chrome M35 as per documented in this bug. Mozilla followed up with parity and landed the support in Firefox 55.

As explained by Rick Byers in the this Chrome issue:

The spec has an example that says:

"The user's environment might be configured to associate vertical scrolling with rotation along the y-axis, horizontal scrolling with rotation along the x-axis, and zooming with rotation along the z-axis."

From this perspective it seems reasonable to generate deltaZ wheel events for trackpad pinch gestures.  This would enable apps like google maps to respond nicely to pinch.

So that was a bit of the historic context. Today this means that we have a de-facto “hack” standard to detect pinch-to-zoom gestures from trackpads, which is supported in multiple browsers.

Detecting pinch-to-zoom on your trackpad with JavaScript

So how does it work?

You can detect a pinch-to-zoom gesture with this quite simple event handler listening for the wheel event, where the e.deltaY value represents your zoom/scale factor when the e.ctrlKey is set.

That’s it.

<script src="https://gist.github.com/auchenberg/9eae2e61ba01e0ea8747c8268ed5c8fd.js"></script>

What browsers does this work in?

The browser support seems to be as following:

Detecting more advanced trackpad gestures with GesturesEvents in Webkit

After the ctrl key modifer hacker landed there seem to have been a discussion on how this could formalized into a better API as per this dicussion on Twitter:

In March 2016 Apple has shipped new aGestureEvent for Webkit that shipped as a part of Safari 9.1, and this new event model allow us to detect gesture rotation and much.

You can read more about GestureEvents in the Apple documentation here: https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW23

Demo using a combination of wheel + gesture events

I’ve put together a simple demo of a <div> which you can move around and scale using your multi-touch trackpad, which is using a combination of the wheel event and gestureEvents when in Webkit. The latter enables rotation of the element, which is quite cool:

Demo: https://multi-touch-trackpad-gesture.stackblitz.io/
Code: https://stackblitz.com/edit/multi-touch-trackpad-gesture

[https://multi-touch-trackpad-gesture.stackblitz.io/](https://multi-touch-trackpad-gesture.stackblitz.io/) https://multi-touch-trackpad-gesture.stackblitz.io/

Another cool demo I found is using WebGL and the performance is even better: http://jsbin.com/fepuficudolo/3/edit?html,output

Towards standardization

Today there doesn't seem to be a web standard for this, but there’s requests opened on the W3C UI Events specification here https://github.com/w3c/uievents/issues/31, and there’s a separate discussion on extending PointerEvents to expose raw Trackpad events here https://github.com/w3c/pointerevents/issues/206, so maybe one day we’ll have a web standard for this. Personally I would expect PointerEvents as the place for this.

Hope that clarified a few things. At least it did for me.

/k