/** * 弹框 */ cc.Class({ extends: cc.Component, properties: { id: { default: JMC.ALERT_ID.DEFAULT, type: JMC.ALERT_ID, tooltip: '弹框 Id' }, enableOutside: { default: false, tooltip: '是否响应:点击遮挡关闭弹框' }, enableBack: { default: false, tooltip: '是否响应:点击返回键关闭弹框' }, isBlockOutside: { default: true, tooltip: '是否阻挡:点击穿透\n注意:遮挡时,请添加 Button 组件来响应 blockOnClicked' }, autoPlayAnim: { default: false, tooltip: '是否自动播放弹出/关闭动画(在 onLoad 播放)' }, isShowing: { default: false, visible: false }, isHiding: { default: false, visible: false }, enableAction: { visible: false, get () { return (!this.isShowing && !this.isHiding); } }, alertZIndex: { default: 0, tooltip: '弹框弹出的层次,越大值越在顶层。0是默认值,值>=100时,popAllAlert接口将不处理它' }, rootNode: { default: undefined, type: cc.Node, tooltip: '播放弹出/关闭动画中缩放的节点。如果为空则无弹出/关闭动画' } }, /** * 生命周期。子类需要调用this._super() * * @author Pyden * @date 2019-03-25 */ onLoad () { // 穿透的特殊处理 if (!this.isBlockOutside) { // 注意:_hitTest方法,需要调用this.node.on才会执行到 this.node._hitTest = (point, listener) => { this.blockOnClicked(); return false; }; } this.isShowing = false; this.isHiding = false; if (!CC_EDITOR) { if (this.autoPlayAnim) { this.playShowAnim(); } } }, /** * 生命周期。子类需要调用this._super() * * @author Pyden * @date 2019-03-25 */ onEnable () { this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this); }, /** * 生命周期。子类需要调用this._super() * * @author Pyden * @date 2019-03-25 */ onDisable () { this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this); }, /** * 生命周期。子类需要调用this._super() * * @author Pyden * @date 2019-07-22 */ onDestroy () { }, /** * AlertCtrl.showAlert 方法统一调用刷新弹框的方法 * * @author Pyden * @date 2019-04-23 * @param {Object} viewData * @param {Function} cb */ reloadData (viewData, cb) { this.cb = cb; }, /** * 回调消息 * * @author Pyden * @date 2019-04-26 * @param {String} eventKey 事件Key * @param {Any} eventData 附加信息 */ alertCallback (eventKey, eventData) { if (this.cb) { // 因为cb如果出错会导致游戏闪屏,所以加上try catch try { this.cb(this, eventKey, eventData); } catch (error) { G.LogUtils.error('alert call back error:', error); } } else { this.alertDefaultCallback(eventKey, eventData); } }, /** * 弹框默认事件的处理 * * @author Pyden * @date 2019-04-26 * @param {String} eventKey 事件Key * @param {Any} eventData 附加信息 */ alertDefaultCallback (eventKey, eventData) { switch (eventKey) { case 'error': { // 出错了,继续停留在弹框 break; } case 'willShow': { // 弹框将要展示 break; } case 'hideDone': { // 弹框隐藏完毕 break; } default: { // 关闭 this.close(); break; } } }, /** * 点击遮挡 * * @author Pyden * @date 2019-03-25 */ blockOnClicked () { G.LogUtils.log('blockOnClicked'); if (!this.enableOutside) { G.LogUtils.log('!this.enableOutside'); return; } this.closeOnClicked(); }, /** * 点击返回键 * * @author Pyden * @date 2019-03-25 */ backKeyOnClicked () { if (!this.enableBack) { return; } this.closeOnClicked(); }, /** * 点击关闭。包括3种:点击关闭按钮、点击遮挡、点击返回键 * * @author Pyden * @date 2019-03-25 */ closeOnClicked () { if (!this.enableAction) { return; } // G.AudioMgr.playEffect('res_audio/mp3/sound/click', false); this.alertCallback('clickedClose'); }, /** * 关闭弹框 * * @author Pyden * @date 2019-03-25 */ close () { this.playHideAnim(() => { // 播放隐藏动画完毕向cb发送一个hideDone消息 this.alertCallback('hideDone'); let event = new cc.Event.EventCustom('e_alert_pop', true); event.setUserData(this); this.node.dispatchEvent(event); }); }, /** * 播放弹出动画:淡入 * 注意:弹出过程中,不响应交互 * * @author Pyden * @date 2019-03-28 * @param {function} cb 弹出后的回调 */ playShowAnim (cb) { if (!this.rootNode) { if (cb) { cb(this); } return; } if (this.isShowing) { return; } this.isShowing = true; this.isHiding = false; let animTime = 0.2; this.rootNode.scale = 0.1; cc.tween(this.rootNode) .stop() .to(animTime - 0.1, {scale: 1.06}) .to(0.07, {scale: 0.98}) .to(0.03, {scale: 1}) .start(); this.node.opacity = 255 * 0.2; cc.tween(this.node) .stop() .to(animTime, {opacity: 255}) .call(() => { this.isShowing = false; if (cb) { cb(this); } }) .start(); }, /** * 播放关闭动画:淡出 * 注意:弹出过程中,不响应交互 * * @author Pyden * @date 2019-03-28 * @param {function} cb 关闭后的回调 */ playHideAnim (cb) { if (!this.rootNode) { if (cb) { cb(this); } return; } if (this.isHiding) { return; } this.isShowing = false; this.isHiding = true; let animTime = 0.1; cc.tween(this.rootNode) .stop() .to(animTime, {scale: 0}) .start(); cc.tween(this.node) .stop() .to(animTime, {opacity: 0}) .call(() => { this.isHiding = false; if (cb) { cb(this); } }) .start(); }, /** * 通用的按钮点击回调 * 根据customEventData去cb * * @author libo * @date 2019-04-12 * @param {Object} event * @param {String} customEventData */ emitCustomEventData (event, customEventData) { if (!customEventData) { G.LogUtils.error('[emitCustomEventData] customEventData不能是空'); return; } this.alertCallback(customEventData); }, // ---------------- 私有方法分割线 ---------------- /** * 开始触摸 * * @author Pyden * @date 2019-03-25 * @param {*} event */ _onTouchStart (event) { if (this.isBlockOutside) { // 遮挡时,请添加 Button 组件来响应 blockOnClicked event.stopPropagation(); } } });