vue-app-touch
Version:
124 lines (110 loc) • 4.2 kB
text/typescript
interface Pos {
x: number;
y: number;
}
export default class MTouch {
private tracking = false;
private lastTapTime = 0;
private spos: Pos;
private epos: Pos;
private maxDistance: number;
private tapInterval: number;
private openPress: boolean;
private pressTime: number;
private pressTimeId: number;
public constructor(target: HTMLElement, option?: { maxDistance?: number, tapInterval?: number, openPress?: boolean, pressTime?: number }) {
target.addEventListener('touchstart', this, false);
target.addEventListener('touchmove', this, false);
target.addEventListener('touchend', this, false);
target.addEventListener('touchcancel', this, false);
this.maxDistance = option && option.maxDistance || 5;
this.tapInterval = option && option.tapInterval || 800;
this.openPress = option && option.openPress || false;
this.pressTime = option && option.pressTime || 650;
}
public handleEvent(e: TouchEvent) {
const type = e.type;
const touche = e.touches[0];
const target = e.target as HTMLElement;
switch (type) {
case 'touchstart':
if (e.targetTouches.length > 1) {
this.tracking = false;
this.openPress && this.clearPress();
return true;
}
this.tracking = true;
this.spos = {
x: touche.pageX,
y: touche.pageY
}
this.epos = {
x: touche.pageX,
y: touche.pageY
}
this.openPress && this.press(target);
break;
case 'touchmove': {
this.epos = {
x: touche.pageX,
y: touche.pageY
};
const distance = this.getDistance(this.spos, this.epos);
this.openPress && distance > this.maxDistance && this.clearPress();
break;
}
case 'touchend': {
this.openPress && this.clearPress();
if (!this.tracking) {
return true;
}
const fingers = this.getFingers(e);
const distance = this.getDistance(this.spos, this.epos);
if (fingers === 0 && distance <= this.maxDistance && e.timeStamp - this.lastTapTime > this.tapInterval) {
e.stopPropagation();
this.lastTapTime = e.timeStamp;
this.sendTap(target);
}
break;
}
case 'touchcancel':
this.openPress && this.clearPress();
break;
}
}
private getDistance(p1: Pos, p2: Pos) {
const x = p2.x - p1.x;
const y = p2.y - p1.y;
return Math.sqrt((x * x) + (y * y));
}
private getFingers(evt: TouchEvent) {
return evt.touches && evt.touches.length || 0;
}
private press(target: HTMLElement) {
this.pressTimeId = setTimeout(() => {
this.tracking = false;
this.sendPress(target);
}, this.pressTime);
}
private clearPress() {
if (this.pressTimeId) {
clearTimeout(this.pressTimeId);
this.pressTimeId = 0;
}
}
private sendTap(target: HTMLElement) {
const targetElement = target.nodeType === Node.TEXT_NODE ? target.parentNode : target;
const evt = document.createEvent('HTMLEvents');
evt.initEvent('tap', true, true);
targetElement.dispatchEvent(evt);
}
private sendPress(target: HTMLElement) {
const targetElement = target.nodeType === Node.TEXT_NODE ? target.parentNode : target;
const evt = document.createEvent('HTMLEvents');
evt.initEvent('press', true, true);
targetElement.dispatchEvent(evt);
}
}
new MTouch(document.body, {
openPress: true
});