Skip to content

Instantly share code, notes, and snippets.

@finscn
Last active January 25, 2020 18:49
Show Gist options
  • Save finscn/082cb1eef97de915f977eebeba92ccf3 to your computer and use it in GitHub Desktop.
Save finscn/082cb1eef97de915f977eebeba92ccf3 to your computer and use it in GitHub Desktop.
Touch lib for cocos creator 2.x
// export { default as Tap } from "./Tap";
// export { default as DoubleTap } from "./DoubleTap";
// export { default as Swipe } from "./Swipe";
const { ccclass, property } = cc._decorator;
@ccclass
export default class Toucher extends cc.Component {
@property
tap: boolean = false;
@property
doubleTap: boolean = false;
@property
tapDuration: number = 300;
@property
tapRadius: number = 50;
@property
pan: boolean = false;
@property
swipe: boolean = false;
@property
swipeDuration: number = 1000;
@property
swipeMinDistance: number = 100;
@property
swipeMaxDistance: number = 1000;
disabled: boolean = false;
touched: boolean = false;
touchedID: number = -1;
startTime: number = 0;
startCanvasPos: cc.Vec2 = null;
_prevTapPos: cc.Vec2 = null;
_prevTapTime: number = 0;
_tapIndex: number = 0;
onStart: TouchCallback = null;
onMove: TouchCallback = null;
onEnd: TouchCallback = null;
onTap: TapCallback = null;
onDoubleTap: TapCallback = null;
onPan: PanCallback = null;
onSwipeUp: SwipeCallback = null;
onSwipeDown: SwipeCallback = null;
onSwipeLeft: SwipeCallback = null;
onSwipeRight: SwipeCallback = null;
reset() {
this.touchedID = -1;
this.startTime = 0;
this.startCanvasPos = null;
}
registerInput(node: cc.Node, useCapture: boolean = true) {
let tapRadiusSq = this.tapRadius * this.tapRadius;
// listen TOUCH_START
node.on(cc.Node.EventType.TOUCH_START, (event: cc.Event.EventTouch) => {
this.touched = true;
if (this.disabled === true) {
return;
}
this.touchedID = event.getID();
this.startTime = Date.now();
let pos = event.getLocation();
if (this.onStart) {
this.onStart(pos.x, pos.y, event);
}
this.startCanvasPos = pos;
}, null, useCapture);
// listen TOUCH_MOVE
node.on(cc.Node.EventType.TOUCH_MOVE, (event: cc.Event.EventTouch) => {
if (this.disabled === true) {
return;
}
let pos = event.getLocation();
if (this.onMove) {
this.onMove(pos.x, pos.y, event);
}
if (event.getID() !== this.touchedID) {
this.reset();
return;
}
// for more gestures ...
// Pan
if (this.pan && this.touched && this.onPan) {
this.onPan(pos.x, pos.y, event);
event.stopPropagation();
}
}, null, useCapture);
// listen TOUCH_END
node.on(cc.Node.EventType.TOUCH_END, (event: cc.Event.EventTouch) => {
this.touched = false;
if (this.disabled === true) {
return;
}
let endPos = event.getLocation();
let endTime = Date.now();
if (this.onEnd) {
this.onEnd(endPos.x, endPos.y, event);
}
if (event.getID() !== this.touchedID) {
this.reset();
return;
}
// for more gestures ...
let startTime = this.startTime;
let startPos = this.startCanvasPos;
if (!startPos) {
this.reset();
return;
}
let duration = endTime - startTime;
let dx = endPos.x - startPos.x;
let dy = endPos.y - startPos.y;
let distanceSq = dx * dx + dy * dy;
let _doubleTap: boolean = false;
if (this.doubleTap && this.onDoubleTap
&& duration < this.tapDuration && distanceSq < tapRadiusSq) {
// Double Tap
if (this._tapIndex === 1) {
let _duration = startTime - this._prevTapTime;
let _x = this._prevTapPos.x;
let _y = this._prevTapPos.y;
let _dx = startPos.x - _x;
let _dy = startPos.y - _y;
let _distanceSq = _dx * _dx + _dy * _dy;
if (_duration < this.tapDuration && _distanceSq < tapRadiusSq) {
_doubleTap = true;
this.onDoubleTap(_x, _y, event);
}
this._tapIndex = 0;
event.stopPropagation();
}
}
if (!_doubleTap && this.tap && this.onTap
&& duration < this.tapDuration && distanceSq < this.tapRadius * this.tapRadius) {
// Single Tap
this._tapIndex++;
this.onTap(startPos.x, startPos.y, event);
this._prevTapPos = startPos;
this._prevTapTime = endTime;
event.stopPropagation();
} else if (this.swipe && duration < this.swipeDuration) {
let dist = Math.sqrt(distanceSq);
if (dist > this.swipeMinDistance && dist < this.swipeMaxDistance) {
// Swipe
let verticalSwipe = Math.abs(dy) > Math.abs(dx);
let vel = dist / duration;
if (verticalSwipe && dy > 0) {
this.onSwipeUp && this.onSwipeUp(vel, event);
} else if (verticalSwipe) {
this.onSwipeDown && this.onSwipeDown(vel, event);
} else if (!verticalSwipe && dx > 0) {
this.onSwipeRight && this.onSwipeRight(vel, event);
} else {
this.onSwipeLeft && this.onSwipeLeft(vel, event);
}
this._tapIndex = 0;
event.stopPropagation();
}
}
}, null, useCapture);
}
}
interface TouchCallback {
(x: number, y: number, event: cc.Event.EventTouch): void;
}
interface TapCallback {
(x: number, y: number, event: cc.Event.EventTouch): void;
}
interface PanCallback {
(x: number, y: number, event: cc.Event.EventTouch): void;
}
interface SwipeCallback {
(vel: number, event: cc.Event.EventTouch): void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment