We manage to determine trackpad usage by first assuming an OSX machine has it and then working to detect if that user has a mouse plugged in. Excuse me, because we use typescript, but it will work in javascript.
First, just look at the user agent properties, and then if OSX, assume it has one. I just use some basic string expressions on the user agent to determine what the OS is.
if (!props.isMobile && props.operatingSystem === OSType.Darwin) {
props.hasTouchpad = true
props.hasGestureSupport = props.browser === BrowserType.Safari | props.isMobile
}
Now work to eliminate that device by listening to the wheel event. A trackpad device will create really small deltaY values that are non-integer. I have tried this and it does a very good job.
const detectMouseType = useCallback((e:WheelEvent) => {
if (e.ctrlKey || !browserProperties.hasTouchpad) {
//Didn't detect originally, or pinch zoom OSX and surface, ignore
return
}
let isMouse = e.deltaX === 0 && !Number.isInteger(e.deltaY)
isMouseCounts.push(isMouse ? 1 : 0)
if (isMouseCounts.length > 5) isMouseCounts.shift()
let sum = isMouseCounts.reduce(function(a, b) { return a + b; });
if (sum > 3 && e.type === "wheel") {
console.log("Touchpad disabled")
//detected a mouse not a touchpad, maybe a mouse plugged into a mac
document.removeEventListener('wheel', detectMouseType);
props.hasTouchpad = false
props.hasGestureSupport = false
}
}, [])
Now onto using trackpad events and detecting pinch in browsers that normally don't support it (HammerJS for example):
On OSX Safari and iOS Safari the "gesturestart" and "gesturechange" events are fired which are sufficient for detecting pinch and rotate. There are scale and rotate parameters you can use to get the data you need.
Here's some code to get you started:
https://medium.com/@auchenberg/detecting-multi-touch-trackpad-gestures-in-javascript-a2505babb10e
On OSX Chrome, you can use the "wheel" event to detect pinch, scroll, and two finger tap. Most solutions you'll see will not support pinch or two finiger tap on OSX Chrome, but this will. Here's how two finger tap and pinch are done for Chrome and also mice on all other browsers:
let scale = 1.0;
let posX = 0.0;
let posY = 0.0;
element.addEventListener('wheel', (e) => {
e.preventDefault();
if (e.ctrlKey) {
//using two fingers
if (e.deltaY === 0 && e.deltaX === 0) {
console.log("Chrome two finger tap detected")
} else {
console.log("pinch zoom")
scale = scale - e.deltaY * 0.01
}
} else {
console.log('scrolling')
posX = posX - e.deltaX * 2
posY = posY - e.deltaY * 2
}
});