Skip to content

Instantly share code, notes, and snippets.

@gseok
Created February 5, 2021 10:58
Show Gist options
  • Save gseok/086449a1b1bdaf95bd9d93d0b2c2869d to your computer and use it in GitHub Desktop.
Save gseok/086449a1b1bdaf95bd9d93d0b2c2869d to your computer and use it in GitHub Desktop.
Simple Swipe control util class with ts
export interface TouchEventExt extends TouchEvent {
center: {
x: number;
y: number;
};
}
class Swipe {
element: HTMLElement;
lastTouchEvent: TouchEventExt;
prevTouchEvent: TouchEventExt;
y: number;
x: number;
xDiff: number;
yDiff: number;
events: { [key: string]: Function[] };
constructor(element: HTMLElement) {
this.events = {};
this.x = null;
this.y = null;
this.prevTouchEvent = null;
this.lastTouchEvent = null;
this.element = element;
this._handleTouchStart = this._handleTouchStart.bind(this);
this._handleTouchMove = this._handleTouchMove.bind(this);
this._handleTouchEnd = this._handleTouchEnd.bind(this);
this._listenStart();
}
static indexOf(store: Function[], target: Function) {
if (typeof Array.prototype.indexOf === 'function') {
return store.indexOf(target);
}
let i = 0;
const { length } = store;
let idx = -1;
let found = false;
while (i < length && !found) {
if (store[i] === target) {
idx = i;
found = true;
}
i += 1;
}
return idx;
}
_listenStart() {
if (!this.element) return;
this.element.addEventListener('touchstart', this._handleTouchStart);
}
_listenMove() {
if (!this.element) return;
this.element.addEventListener('touchmove', this._handleTouchMove);
}
_listenEnd() {
if (!this.element) return;
this.element.addEventListener('touchend', this._handleTouchEnd);
}
_handleTouchEnd() {
this.emit('end', this.lastTouchEvent);
this.element.removeEventListener('touchmove', this._handleTouchMove);
this.element.removeEventListener('touchend', this._handleTouchEnd);
}
_handleTouchStart(evt: TouchEvent) {
this.x = evt.touches[0].clientX;
this.y = evt.touches[0].clientY;
const { x, y } = this;
this.prevTouchEvent = Object.assign(evt, { center: { x, y } });
this.lastTouchEvent = this.prevTouchEvent;
this.emit('start', this.lastTouchEvent);
this._listenMove();
this._listenEnd();
}
_handleTouchMove(evt: TouchEvent) {
if (!this.x || !this.y) {
return;
}
const xNew = evt.touches[0].clientX;
const yNew = evt.touches[0].clientY;
const event = Object.assign(evt, { center: { x: xNew, y: yNew } });
this.prevTouchEvent = this.lastTouchEvent;
this.lastTouchEvent = event;
this.emit('move', event);
this.xDiff = this.x - xNew;
this.yDiff = this.y - yNew;
if (Math.abs(this.xDiff) > Math.abs(this.yDiff)) {
// Most significant.
if (this.xDiff > 0) {
this.emit('left', event);
} else {
this.emit('right', event);
}
} else if (this.yDiff > 0) {
this.emit('up', event);
} else {
this.emit('down', event);
}
// Reset values.
this.x = xNew;
this.y = yNew;
}
destroy() {
this.element.removeEventListener('touchstart', this._handleTouchStart);
this.element.removeEventListener('touchmove', this._handleTouchMove);
this.element.removeEventListener('touchend', this._handleTouchEnd);
}
on(event: string, listener: Function) {
if (typeof this.events[event] !== 'object') {
this.events[event] = [];
}
this.events[event].push(listener);
}
emit(event: string, args?: TouchEventExt) {
if (typeof this.events[event] === 'object') {
const listeners = this.events[event].slice();
const { length } = listeners;
for (let i = 0; i < length; i += 1) {
const fn = listeners[i];
fn(args);
}
}
}
removeListener(event: string, listener: Function) {
if (typeof this.events[event] === 'object') {
const idx = Swipe.indexOf(this.events[event], listener);
if (idx > -1) {
this.events[event].splice(idx, 1);
}
}
}
removeAllListener() {
this.events = {};
}
}
export default Swipe;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment