TouchHelper.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. const { ccclass, property } = cc._decorator;
  2. /**
  3. * @description 触摸辅助器,支持多边形区域点击检测,并且添加ceator不带有的tap事件
  4. * @author Soonsky
  5. */
  6. @ccclass
  7. export class TouchHelper extends cc.Component {
  8. @property({ tooltip: "是否可以点击" }) canTouch: boolean = true;
  9. @property({ tooltip: "在多边形范围内产生点击", type: cc.Component.EventHandler }) onInPolygon: cc.Component.EventHandler = null;
  10. @property({ tooltip: "在多边形范围外产生点击", type: cc.Component.EventHandler }) onOutPolygon: cc.Component.EventHandler = null;
  11. @property({ tooltip: "在节点范围内产生点击", type: cc.Component.EventHandler }) onTouchTap: cc.Component.EventHandler = null;
  12. @property({ tooltip: "是否与需要多边形检查" }) needPolygon: boolean = true;
  13. @property({ type: [cc.Vec2], tooltip: "多边形定点位置信息(局部坐标,至少3个点)" }) points: Array<cc.Vec2> = [];
  14. @property({ tooltip: "点击在多边形区域内时是否阻止事件冒泡" }) stopPropagation = false;
  15. @property({tooltip: '是否点击有缩放效果'})
  16. private isScaleAct: boolean = true;
  17. private isMoved = false;
  18. private isStart = false;
  19. start() {
  20. this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
  21. this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
  22. this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
  23. this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
  24. this.node['_touchListener'].swallowTouches = false;
  25. }
  26. private onTouchEnd(e): void {
  27. if (!this.isMoved) {
  28. if (this.isStart) {
  29. if (this.stopPropagation) {
  30. e.propagationStopped = true;
  31. }
  32. if(this.canTouch)
  33. {
  34. this.onInPolygon && this.onInPolygon.emit([]);
  35. this.onTouchTap && this.onTouchTap.emit([]);
  36. }
  37. mk.audio.playEffect('button');
  38. if(this.isScaleAct)
  39. {
  40. cc.tween(this.node).to(0.1, {scale: 1}).start();
  41. console.log(`------end${this.name}`);
  42. }
  43. } else {
  44. this.canTouch && this.onOutPolygon && this.onOutPolygon.emit([]);
  45. }
  46. }
  47. this.isStart = false;
  48. this.isMoved = false;
  49. }
  50. private onTouchMove(e: cc.Event.EventTouch) {
  51. if (e.getTouches().length > 1) { this.isMoved = true; return }
  52. this.isMoved = cc.Vec2.distance(e.getStartLocation(), e.getLocation()) > 20;
  53. //let touchPoint = e.getLocation();
  54. //let localPoint = this.node.convertToNodeSpaceAR(touchPoint);
  55. //this.isMoved = !cc.Intersection.pointInPolygon(localPoint, this.points);//!this.pointInPoly(localPoint, this.points);
  56. if(this.isScaleAct && this.isMoved)
  57. {
  58. console.log(`------move${this.name}`);
  59. cc.tween(this.node).to(0.1, {scale: 1}).start();
  60. }
  61. }
  62. private onTouchCancel(e: cc.Event.EventTouch) {
  63. this.isMoved = false;
  64. if(this.isScaleAct)
  65. {
  66. this.node.setScale(1);
  67. }
  68. }
  69. private onTouchStart(e: cc.Event.EventTouch){
  70. if (this.canTouch && this.needPolygon && this.points.length >= 3) {
  71. let touchPoint = e.getLocation();
  72. let localPoint = this.node.convertToNodeSpaceAR(touchPoint);
  73. this.isStart = cc.Intersection.pointInPolygon(localPoint, this.points)//this.pointInPoly(localPoint, this.points);
  74. }
  75. if(this.isScaleAct && this.isStart)
  76. {
  77. cc.tween(this.node).to(0.1, {scale: 1.1}).start();
  78. console.log(`------start${this.name}`);
  79. }
  80. }
  81. private pointInPoly(point: cc.Vec2 | cc.Vec3, polyPoints: cc.Vec2[]) {
  82. for (var c = false, i = -1, l = polyPoints.length, j = l - 1; ++i < l; j = i)
  83. ((polyPoints[i].y <= point.y && point.y < polyPoints[j].y) || (polyPoints[j].y <= point.y && point.y < polyPoints[i].y))
  84. && (point.x < (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x)
  85. && (c = !c);
  86. return c;
  87. }
  88. }