const { ccclass, property } = cc._decorator; /** * @description 触摸辅助器,支持多边形区域点击检测,并且添加ceator不带有的tap事件 * @author Soonsky */ @ccclass export class TouchHelper extends cc.Component { @property({ tooltip: "是否可以点击" }) canTouch: boolean = true; @property({ tooltip: "在多边形范围内产生点击", type: cc.Component.EventHandler }) onInPolygon: cc.Component.EventHandler = null; @property({ tooltip: "在多边形范围外产生点击", type: cc.Component.EventHandler }) onOutPolygon: cc.Component.EventHandler = null; @property({ tooltip: "在节点范围内产生点击", type: cc.Component.EventHandler }) onTouchTap: cc.Component.EventHandler = null; @property({ tooltip: "是否与需要多边形检查" }) needPolygon: boolean = true; @property({ type: [cc.Vec2], tooltip: "多边形定点位置信息(局部坐标,至少3个点)" }) points: Array = []; @property({ tooltip: "点击在多边形区域内时是否阻止事件冒泡" }) stopPropagation = false; @property({tooltip: '是否点击有缩放效果'}) private isScaleAct: boolean = true; private isMoved = false; private isStart = false; start() { this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this); this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this); this.node['_touchListener'].swallowTouches = false; } private onTouchEnd(e): void { if (!this.isMoved) { if (this.isStart) { if (this.stopPropagation) { e.propagationStopped = true; } if(this.canTouch) { this.onInPolygon && this.onInPolygon.emit([]); this.onTouchTap && this.onTouchTap.emit([]); } mk.audio.playEffect('button'); if(this.isScaleAct) { cc.tween(this.node).to(0.1, {scale: 1}).start(); // console.log(`------end${this.name}`); } } else { this.canTouch && this.onOutPolygon && this.onOutPolygon.emit([]); } } this.isStart = false; this.isMoved = false; } private onTouchMove(e: cc.Event.EventTouch) { if (e.getTouches().length > 1) { this.isMoved = true; return } this.isMoved = cc.Vec2.distance(e.getStartLocation(), e.getLocation()) > 20; //let touchPoint = e.getLocation(); //let localPoint = this.node.convertToNodeSpaceAR(touchPoint); //this.isMoved = !cc.Intersection.pointInPolygon(localPoint, this.points);//!this.pointInPoly(localPoint, this.points); if(this.isScaleAct && this.isMoved) { // console.log(`------move${this.name}`); cc.tween(this.node).to(0.1, {scale: 1}).start(); } } private onTouchCancel(e: cc.Event.EventTouch) { this.isMoved = false; if(this.isScaleAct) { this.node.setScale(1); } } private onTouchStart(e: cc.Event.EventTouch){ if (this.canTouch && this.needPolygon && this.points.length >= 3) { let touchPoint = e.getLocation(); let localPoint = this.node.convertToNodeSpaceAR(touchPoint); this.isStart = cc.Intersection.pointInPolygon(localPoint, this.points)//this.pointInPoly(localPoint, this.points); } if(this.isScaleAct && this.isStart) { cc.tween(this.node).to(0.1, {scale: 1.1}).start(); // console.log(`------start${this.name}`); } } private pointInPoly(point: cc.Vec2 | cc.Vec3, polyPoints: cc.Vec2[]) { for (var c = false, i = -1, l = polyPoints.length, j = l - 1; ++i < l; j = i) ((polyPoints[i].y <= point.y && point.y < polyPoints[j].y) || (polyPoints[j].y <= point.y && point.y < polyPoints[i].y)) && (point.x < (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x) && (c = !c); return c; } }