import { _decorator, Button, Component, easing, EventHandler, EventTouch, js, Node, Tween, tween, UITransform, Vec2, Vec3 } from 'cc'; import { Utils } from '../../utils/Utils'; import { Logger } from '../../extend/Logger'; import { uiMgr } from '../manager/UIManager'; import { eventEmitter } from '../event/EventEmitter'; import { initAutoBindings } from '../../extend/AutoBind'; import { Constants } from '../../data/Constants'; import { audioMgr } from '../manager/AudioManager'; const { ccclass, property } = _decorator; @ccclass('BaseExp') export class BaseExp extends Component { //事件数组 private events:any[] = []; //是否允许点击空白关闭页面,默认true public closeOnBlank: boolean = true; //是否有出场放大的动画 默认true private _hasAnim: boolean = true; public set hasAnim(value: boolean) { if(value){ this.showAnim(); } this._hasAnim = value; } private oScale: Vec3 = Vec3.ZERO; private uiBG: Node = null; public onLoad() { this.events = []; //加入按钮点击 this._addClickEvent(this.node); //自动绑定属性 initAutoBindings(this); //监听节点点击事件 this.node.on(Node.EventType.TOUCH_END, this.onNodeTouchEnd, this); //背景视图 this.uiBG = this.node.getChildByName("UI"); if(this.uiBG){ this.oScale = this.uiBG.scale.clone(); } } /** * 展示加载缓动动画 */ public showAnim(){ if(this.uiBG && this._hasAnim){ Tween.stopAllByTarget(this.uiBG); this.uiBG.scale = new Vec3(0.95,0.95,0.95); let scale: Vec3 = this.oScale; tween(this.uiBG) .to(0.1, {scale: new Vec3(0.02 + scale.x,0.02 + scale.y,0.02 + scale.z)},{easing: easing.backOut}) .to(0.1, {scale: new Vec3(scale.x - 0.02,scale.y - 0.02,scale.z - 0.02)},{easing: easing.backOut}) .call(() => { this.uiBG.scale = this.oScale; }).start(); } } /** * 节点触摸结束事件处理 * @param event 触摸事件 */ private onNodeTouchEnd(event: EventTouch) { const uiBG = this.node.getChildByName("UI"); if (!uiBG || !this.closeOnBlank)return; let trans: UITransform = this.node.getComponent(UITransform); const location = event.getUILocation(); let pos = trans.convertToNodeSpaceAR(new Vec3(location.x,location.y)); if(!uiBG.getComponent(UITransform).getBoundingBox().contains(new Vec2(pos.x,pos.y))){ this.close(); } } /** * 关闭页面 * @param cb 关闭页面的回调 */ private close(cb?: Function){ let pagePath: string = this.node["_uiPath"]; if(!Utils.isNull(pagePath)){ uiMgr.hide(pagePath,cb); }else{ Logger.log(`请检查该: ${this.node.name}页面路径信息,不存在`); } } /** * 点击事件 * @param event 事件 * @param customEventData 数据 */ public onBtnClicked(event:EventTouch, customEventData:any) { audioMgr.playOneShot(Constants.audios.click); let btnName = event.target.name; if(btnName === 'close_btn'){ this.close(); } } /** * 是否允许添加 * @param node 添加的节点 */ private _isSkipNode(node: Node): boolean { if(this.node == node) { return false; } let b = node.getComponent(BaseExp); if (b) //Logger.log("跳过", b.name) return b != null; } /** * 加入点击事件 * @param node 加入点击的节点 */ private _addClickEvent(node: Node) { if (this._isSkipNode(node)) return; for (let i = 0; i < node.children.length; i++) { let n:Node = node.children[i]; if(this._isSkipNode(n)) continue; if(n.getComponent(Button)) { this.addClickEvent(n, this.node, js.getClassName(this), "onBtnClicked", n); } this._addClickEvent(n); } } /** * 加入按钮点击事件 * @param node 点击的节点 * @param target 点击的对象 * @param component 组建的类名 * @param handler 处理的具柄 * @param customEventData 传递的数据 */ private addClickEvent(node, target, component, handler, customEventData) { let eventHandler = new EventHandler() eventHandler.target = target; eventHandler.component = component; eventHandler.handler = handler; if(customEventData){ eventHandler.customEventData = customEventData; } let clickEvents = node.getComponent(Button).clickEvents; if (clickEvents.length > 0) { Logger.log(`${node.name}按钮已经存在绑定,跳过自动绑定`); return; } clickEvents.push(eventHandler); } //销毁的时候注销所有的事件 public onDestroy() { for(let i = 0; i < this.events.length; i++){ eventEmitter.unregister(this, this.events[i]); } } //注册事件 public register(type: any, cb: Function) { this.events.push(type); eventEmitter.register(this, type, cb); } //取消注册的时间 public unregister(type: any) { eventEmitter.unregister(this, type); } //事件派发 public dispatch(type: any, ...data: any[]) { eventEmitter.dispatch(type, ...data); } }