Last active
January 25, 2020 18:49
-
-
Save finscn/082cb1eef97de915f977eebeba92ccf3 to your computer and use it in GitHub Desktop.
Touch lib for cocos creator 2.x
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
// 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