Created
February 4, 2020 21:07
-
-
Save sepbot/a877850e3d6269b9293bbb8cd07d75e5 to your computer and use it in GitHub Desktop.
somehow implementing these touch event handlers from scratch yielded less code than using something like hammer.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { XY } from './types'; | |
export const setupTouch = ( | |
container: HTMLElement, | |
animate: () => void, | |
tapped: (position: XY) => void, | |
panned: (delta: XY) => void, | |
pinched: (delta: number) => void, | |
) => { | |
const ctx = { | |
max: 0, | |
start: 0, | |
last: { x: 0, z: 0 }, | |
event: new TouchEvent(''), | |
distance: 0, | |
}; | |
container.addEventListener('touchstart', (event) => { | |
ctx.start = performance.now(); | |
ctx.max = event.touches.length; | |
ctx.event = event; | |
const first = event.touches[0]; | |
ctx.last.x = first.clientX; | |
ctx.last.z = first.clientY; | |
animate(); | |
}); | |
container.addEventListener('touchmove', (event) => { | |
// pan | |
if (event.touches.length === 1) { | |
const first = event.touches[0]; | |
// adjust for speed | |
const deltaX = (ctx.last.x - first.clientX) * 0.1; | |
const deltaZ = (ctx.last.z - first.clientY) * 0.1; | |
// avoid erratic movement | |
const deltaXSmooth = deltaX > 0 ? Math.min(deltaX, 0.7) : Math.max(deltaX, -0.7); | |
const deltaZSmooth = deltaZ > 0 ? Math.min(deltaZ, 0.7) : Math.max(deltaZ, -0.7); | |
panned({ x: deltaXSmooth, y: deltaZSmooth }); | |
ctx.last.x = first.clientX; | |
ctx.last.z = first.clientY; | |
ctx.event = event; | |
} | |
// pinch | |
if (event.touches.length > 1) { | |
const first = event.touches[0]; | |
const second = event.touches[1]; | |
const distance = | |
Math.sqrt(Math.pow(second.clientX - first.clientX, 2) + Math.pow(second.clientY - first.clientY, 2)) / 3; | |
const deltaDistance = distance - ctx.distance; | |
const deltaDistanceSmooth = deltaDistance > 0 ? Math.min(deltaDistance, 0.7) : Math.max(deltaDistance, -0.7); | |
ctx.distance = distance; | |
pinched(deltaDistanceSmooth); | |
} | |
animate(); | |
}); | |
container.addEventListener('touchend', () => { | |
// it's a tap | |
if (ctx.max === 1 && performance.now() - ctx.start < 150) { | |
const pointer = { | |
x: (ctx.event.touches[0].clientX / window.innerWidth) * 2 - 1, | |
y: -(ctx.event.touches[0].clientY / window.innerHeight) * 2 + 1, | |
}; | |
tapped(pointer); | |
} | |
ctx.max = 0; | |
ctx.start = 0; | |
ctx.last.x = 0; | |
ctx.last.z = 0; | |
ctx.event = new TouchEvent(''); | |
ctx.distance = 0; | |
animate(); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment