TouchHelper.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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 = false;
  13. @property({ type: [cc.Vec2], tooltip: "多边形定点位置信息(局部坐标,至少3个点)" }) points: Array<cc.Vec2> = [];
  14. @property({ tooltip: "点击在多边形区域内时是否阻止事件冒泡" }) stopPropagation = false;
  15. private isMoved = false;
  16. start() {
  17. this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
  18. this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
  19. this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
  20. }
  21. private onTouchEnd(e): void {
  22. if (this.canTouch && this.needPolygon && this.points.length >= 3) {
  23. let touchPoint = e.touch._point;
  24. let localPoint = this.node.convertToNodeSpaceAR(touchPoint);
  25. let result = this.pointInPoly(localPoint, this.points);
  26. if (!this.isMoved) {
  27. if (result) {
  28. if (this.stopPropagation) {
  29. e.propagationStopped = true;
  30. }
  31. this.canTouch && this.onInPolygon && this.onInPolygon.emit([]);
  32. } else {
  33. this.canTouch && this.onOutPolygon && this.onOutPolygon.emit([]);
  34. }
  35. }
  36. }
  37. if (this.canTouch) {
  38. if (!this.isMoved) {
  39. this.canTouch && this.onTouchTap && this.onTouchTap.emit([]);
  40. }
  41. }
  42. this.isMoved = false;
  43. }
  44. private onTouchMove(e: cc.Event.EventTouch) {
  45. if (e.getTouches().length > 1) { this.isMoved = true; return }
  46. this.isMoved = cc.Vec2.distance(e.getStartLocation(), e.getLocation()) > 20;
  47. }
  48. private onTouchCancel(e: cc.Event.EventTouch) {
  49. this.isMoved = false;
  50. }
  51. private pointInPoly(point: cc.Vec2 | cc.Vec3, polyPoints: cc.Vec2[]) {
  52. for (var c = false, i = -1, l = polyPoints.length, j = l - 1; ++i < l; j = i)
  53. ((polyPoints[i].y <= point.y && point.y < polyPoints[j].y) || (polyPoints[j].y <= point.y && point.y < polyPoints[i].y))
  54. && (point.x < (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x)
  55. && (c = !c);
  56. return c;
  57. }
  58. }