BaseExp.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { _decorator, Button, Component, easing, EventHandler, EventTouch, js, Node, Tween, tween, UITransform, Vec2, Vec3 } from 'cc';
  2. import { Utils } from '../../utils/Utils';
  3. import { Logger } from '../../extend/Logger';
  4. import { uiMgr } from '../manager/UIManager';
  5. import { eventEmitter } from '../event/EventEmitter';
  6. import { initAutoBindings } from '../../extend/AutoBind';
  7. import { Constants } from '../../data/Constants';
  8. import { audioMgr } from '../manager/AudioManager';
  9. const { ccclass, property } = _decorator;
  10. @ccclass('BaseExp')
  11. export class BaseExp extends Component {
  12. //事件数组
  13. private events:any[] = [];
  14. //是否允许点击空白关闭页面,默认true
  15. public closeOnBlank: boolean = true;
  16. //是否有出场放大的动画 默认true
  17. private _hasAnim: boolean = true;
  18. public set hasAnim(value: boolean) {
  19. if(value){
  20. this.showAnim();
  21. }
  22. this._hasAnim = value;
  23. }
  24. private oScale: Vec3 = Vec3.ZERO;
  25. private uiBG: Node = null;
  26. public onLoad() {
  27. this.events = [];
  28. //加入按钮点击
  29. this._addClickEvent(this.node);
  30. //自动绑定属性
  31. initAutoBindings(this);
  32. //监听节点点击事件
  33. this.node.on(Node.EventType.TOUCH_END, this.onNodeTouchEnd, this);
  34. //背景视图
  35. this.uiBG = this.node.getChildByName("UI");
  36. if(this.uiBG){
  37. this.oScale = this.uiBG.scale.clone();
  38. }
  39. }
  40. /**
  41. * 展示加载缓动动画
  42. */
  43. public showAnim(){
  44. if(this.uiBG && this._hasAnim){
  45. Tween.stopAllByTarget(this.uiBG);
  46. this.uiBG.scale = new Vec3(0.95,0.95,0.95);
  47. let scale: Vec3 = this.oScale;
  48. tween(this.uiBG)
  49. .to(0.1, {scale: new Vec3(0.02 + scale.x,0.02 + scale.y,0.02 + scale.z)},{easing: easing.backOut})
  50. .to(0.1, {scale: new Vec3(scale.x - 0.02,scale.y - 0.02,scale.z - 0.02)},{easing: easing.backOut})
  51. .call(() => {
  52. this.uiBG.scale = this.oScale;
  53. }).start();
  54. }
  55. }
  56. /**
  57. * 节点触摸结束事件处理
  58. * @param event 触摸事件
  59. */
  60. private onNodeTouchEnd(event: EventTouch) {
  61. const uiBG = this.node.getChildByName("UI");
  62. if (!uiBG || !this.closeOnBlank)return;
  63. let trans: UITransform = this.node.getComponent(UITransform);
  64. const location = event.getUILocation();
  65. let pos = trans.convertToNodeSpaceAR(new Vec3(location.x,location.y));
  66. if(!uiBG.getComponent(UITransform).getBoundingBox().contains(new Vec2(pos.x,pos.y))){
  67. this.close();
  68. }
  69. }
  70. /**
  71. * 关闭页面
  72. * @param cb 关闭页面的回调
  73. */
  74. private close(cb?: Function){
  75. let pagePath: string = this.node["_uiPath"];
  76. if(!Utils.isNull(pagePath)){
  77. uiMgr.hide(pagePath,cb);
  78. }else{
  79. Logger.log(`请检查该: ${this.node.name}页面路径信息,不存在`);
  80. }
  81. }
  82. /**
  83. * 点击事件
  84. * @param event 事件
  85. * @param customEventData 数据
  86. */
  87. public onBtnClicked(event:EventTouch, customEventData:any) {
  88. audioMgr.playOneShot(Constants.audios.click);
  89. let btnName = event.target.name;
  90. if(btnName === 'close_btn'){
  91. this.close();
  92. }
  93. }
  94. /**
  95. * 是否允许添加
  96. * @param node 添加的节点
  97. */
  98. private _isSkipNode(node: Node): boolean {
  99. if(this.node == node) {
  100. return false;
  101. }
  102. let b = node.getComponent(BaseExp);
  103. if (b) //Logger.log("跳过", b.name)
  104. return b != null;
  105. }
  106. /**
  107. * 加入点击事件
  108. * @param node 加入点击的节点
  109. */
  110. private _addClickEvent(node: Node) {
  111. if (this._isSkipNode(node)) return;
  112. for (let i = 0; i < node.children.length; i++) {
  113. let n:Node = node.children[i];
  114. if(this._isSkipNode(n)) continue;
  115. if(n.getComponent(Button)) {
  116. this.addClickEvent(n, this.node, js.getClassName(this), "onBtnClicked", n);
  117. }
  118. this._addClickEvent(n);
  119. }
  120. }
  121. /**
  122. * 加入按钮点击事件
  123. * @param node 点击的节点
  124. * @param target 点击的对象
  125. * @param component 组建的类名
  126. * @param handler 处理的具柄
  127. * @param customEventData 传递的数据
  128. */
  129. private addClickEvent(node, target, component, handler, customEventData) {
  130. let eventHandler = new EventHandler()
  131. eventHandler.target = target;
  132. eventHandler.component = component;
  133. eventHandler.handler = handler;
  134. if(customEventData){
  135. eventHandler.customEventData = customEventData;
  136. }
  137. let clickEvents = node.getComponent(Button).clickEvents;
  138. if (clickEvents.length > 0) {
  139. Logger.log(`${node.name}按钮已经存在绑定,跳过自动绑定`);
  140. return;
  141. }
  142. clickEvents.push(eventHandler);
  143. }
  144. //销毁的时候注销所有的事件
  145. public onDestroy() {
  146. for(let i = 0; i < this.events.length; i++){
  147. eventEmitter.unregister(this, this.events[i]);
  148. }
  149. }
  150. //注册事件
  151. public register(type: any, cb: Function) {
  152. this.events.push(type);
  153. eventEmitter.register(this, type, cb);
  154. }
  155. //取消注册的时间
  156. public unregister(type: any) {
  157. eventEmitter.unregister(this, type);
  158. }
  159. //事件派发
  160. public dispatch(type: any, ...data: any[]) {
  161. eventEmitter.dispatch(type, ...data);
  162. }
  163. }