Skip to content

Instantly share code, notes, and snippets.

@sepbot
Created February 4, 2020 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sepbot/a877850e3d6269b9293bbb8cd07d75e5 to your computer and use it in GitHub Desktop.
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
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