- From: Alex Kempton <notifications@github.com>
- Date: Fri, 16 Dec 2022 01:04:13 -0800
- To: w3c/uievents <uievents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3c/uievents/issues/337/1354417620@github.com>
Here ya go! Please note that it's not 100% reliable and for Windows users we just completely disable the check and always assume a scrollwheel (so no two-finger panning for Windows users on trackpads). I hope this: - Helps you in your case - Illustrated to the W3C why we desperately need a native solution to this problem ```ts /* For Mac, we want to tell the difference between a touchpad two-finger scroll and a mousewheel. Unfortunately there is no simple way to do this, because both devices trigger a 'wheel' event We can have a good guess with the following assumptions (in priority order): - Mac touchpads never produce deltas with a fractional part - Wheel deltas never happen on the X axis - Wheels often produce the same deltas twice in a row, or some multiple of a delta (e.g. 150, 300, 450) For windows users the above rules do not apply, we treat the wheel event the same, touchpad or mouse. Here's a sandbox for testing this function. Update the function and fork it, share it for user testing: https://codesandbox.io/s/inspiring-hill-b7evw */ import round from "lodash/round" import { isMac } from "./detectPlatform" type ScrollType = "wheel" | "touchPad" | "pinchZoom" | "undetermined" const allowedDivisors = [0.25, 0.5, 0.333, 0.667, 1.5, 2, 3, 4] const trackPadSlowMax = 20 const timeoutMs = 500 let timer: NodeJS.Timeout | undefined // Checks sample of delta values export const checkDeltasAreFromWheel = (arr: number[]) => { let prevVal: number | undefined let isWheel = false let wasOverMax = false let sameCount = 0 let divisorCount = 0 for (let i = 0; i < arr.length; i++) { const v = Math.abs(arr[i]) if (v % 1 !== 0) { // Has irregular fractional part return true } if (prevVal && prevVal !== v) { // Values are different isWheel = false if (v > trackPadSlowMax && prevVal > trackPadSlowMax) { const test = round(v / prevVal, 3) if (allowedDivisors.includes(test)) { // Values are different but neatly divisible divisorCount++ } } } else if (v > trackPadSlowMax) { // Values are same (and not low) sameCount++ } if (v > trackPadSlowMax) { wasOverMax = true } prevVal = v } if (!wasOverMax) { // If the entire sample was under max, we can assume trackpad return false } if (divisorCount > arr.length / 2) { // If more than 50% of consecutive vals had neat divisors, we can assume wheel return true } if (sameCount > arr.length / 2) { // If more than 50% of consecutive vals were the same, we can assume wheel return true } return isWheel } let deltas: number[] = [] export const determineScrollType = (e: WheelEvent): ScrollType => { if (e.ctrlKey) { // ctrlKey is set to true when use pinchzoom on touchpad return "pinchZoom" } else if (!isMac()) { // Non-Mac users always get wheel type return "wheel" } else if (Math.abs(e.deltaX) > 0) { // If the delta is on the X axis, it must be a touchpad return "touchPad" } deltas.unshift(e.deltaY) if (deltas.length > 10) { deltas.pop() } // Clear deltas after some short period in case user has switched between mouse/touchpad if (timer) clearTimeout(timer) timer = setTimeout(() => { deltas = [] }, timeoutMs) if (deltas.length > 2) { return checkDeltasAreFromWheel(deltas) ? "wheel" : "touchPad" } return "undetermined" } ``` -- Reply to this email directly or view it on GitHub: https://github.com/w3c/uievents/issues/337#issuecomment-1354417620 You are receiving this because you are subscribed to this thread. Message ID: <w3c/uievents/issues/337/1354417620@github.com>
Received on Friday, 16 December 2022 09:04:25 UTC