TouchHelper.ts 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { _decorator, Component, Vec2, SystemEventType, EventTouch, UITransform, EventHandler, Vec3, v3 } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. /**
  4. * @description 触摸辅助器,支持多边形区域点击检测,并且添加ceator不带有的tap事件
  5. * @author Soonsky
  6. */
  7. @ccclass('TouchHelper')
  8. export class TouchHelper extends Component {
  9. @property({ tooltip: "是否可以点击" }) canTouch: boolean = true;
  10. @property({ tooltip: "在多边形范围内产生点击", type: EventHandler }) onInPolygon: EventHandler;
  11. @property({ tooltip: "在多边形范围外产生点击", type: EventHandler }) onOutPolygon: EventHandler;
  12. @property({ tooltip: "在节点范围内产生点击", type: EventHandler }) onTouchTap: EventHandler;
  13. @property({ tooltip: "是否与需要多边形检查" }) needPolygon: boolean = false;
  14. @property({ type: [Vec2], tooltip: "多边形定点位置信息(局部坐标,至少3个点)" }) points: Array<Vec2> = [];
  15. @property({ tooltip: "点击在多边形区域内时是否阻止事件冒泡" }) stopPropagation = false;
  16. private isMoved = false;
  17. start() {
  18. this.node.on(SystemEventType.TOUCH_END, this.onTouchEnd, this);
  19. this.node.on(SystemEventType.TOUCH_CANCEL, this.onTouchCancel, this);
  20. this.node.on(SystemEventType.TOUCH_MOVE, this.onTouchMove, this);
  21. }
  22. private onTouchEnd(e: EventTouch): void {
  23. if (this.canTouch && this.needPolygon && this.points.length >= 3) {
  24. let touchPoint = e.getUILocation();
  25. let localPoint = this.node.getComponent(UITransform).convertToNodeSpaceAR(v3(touchPoint.x, touchPoint.y, 0));
  26. let result = this.pointInPoly(localPoint, this.points);
  27. if (!this.isMoved) {
  28. if (result) {
  29. if (this.stopPropagation) {
  30. e.propagationStopped = true;
  31. }
  32. this.canTouch && this.onInPolygon && this.onInPolygon.emit([]);
  33. } else {
  34. this.canTouch && this.onOutPolygon && this.onOutPolygon.emit([]);
  35. }
  36. }
  37. }
  38. if (this.canTouch) {
  39. if (!this.isMoved) {
  40. this.canTouch && this.onTouchTap && this.onTouchTap.emit([]);
  41. }
  42. }
  43. this.isMoved = false;
  44. }
  45. private onTouchMove(e: EventTouch) {
  46. if (e.getAllTouches().length > 1) { this.isMoved = true; return }
  47. this.isMoved = Vec2.distance(e.getStartLocation(), e.getLocation()) > 20;
  48. }
  49. private onTouchCancel(e: EventTouch) {
  50. this.isMoved = false;
  51. }
  52. private pointInPoly(point: Vec2 | Vec3, polyPoints: Vec2[]) {
  53. for (var c = false, i = -1, l = polyPoints.length, j = l - 1; ++i < l; j = i)
  54. ((polyPoints[i].y <= point.y && point.y < polyPoints[j].y) || (polyPoints[j].y <= point.y && point.y < polyPoints[i].y))
  55. && (point.x < (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x)
  56. && (c = !c);
  57. return c;
  58. }
  59. }