cocos creator从零开发简单框架(13)-Panel打开关闭 
                                                    
                        
                    
                    
  
                    
                    编辑framework/scripts/AppConstants.ts,内容如下。定义了Panel的显示方式和遮罩类型,遮罩类型可以叠加,即可同时拥有不可穿透、半透明、关闭组件特性。
// Panel 显示方式
public static readonly panelShowStyle = {
    // 正常出现
    Normal: 1,
    // 中间变大
    CenterSmallToBig: 2,
    // 上往中
    UpToCenter: 3,
    // 下往中
    DownToCenter: 4,
    // 左往中
    LeftToCenter: 5,
    // 右往中
    RightToCenter: 6,
    // 自定义
    Custom: 7,
}
// Panel 遮罩类型
public static readonly panelMaskStyle = {
    // 不可穿透
    NoThrough: 0b1,
    // 半透明
    Black: 0b10,
    // 关闭组件
    Close: 0b100,
}
新建framework/scripts/view/PanelBase.ts,内容如下。定义了显示方式、遮罩类型及Panel显示的过渡时长。
import AppConstants from "../AppConstants"
import ViewBase from "./ViewBase"
export default class PanelBase extends ViewBase {
    public panelName: string
    public panelShowStyle: number = AppConstants.panelShowStyle.Normal
    public panelMaskStyle: number = AppConstants.panelMaskStyle.NoThrough
    public duration: number = 0.2
}
新建framework/scripts/view/PanelMgr.ts,内容如下。
import AppConstants from "../AppConstants"
import AppUtil from "../AppUtil"
import ResMgr from "../manager/ResMgr"
import LayerMgr from "./LayerMgr"
import PanelBase from "./PanelBase"
import TopBlock from "./TopBlock"
export default class PanelMgr {
    // 所有面板
    private static _panels: Map<string, PanelBase> = new Map()
    // 显示 Panel
    public static async show(panelCls: any, ...panelArgs: any[]) {
        TopBlock.show()
        const cls = new panelCls() as PanelBase
        const viewName = cls.getClassName()
        const current = cls
        current.panelName = viewName
        const [panelPrefab, err] = await AppUtil.asyncWrap<cc.Prefab>(ResMgr.load(current.bundleName, current.skinPath))
        if (err) {
            TopBlock.hide()
            console.error(`PanelMgr.show load bundleName:${current.bundleName},skinPath:${current.skinPath},err:${err}`)
            return
        }
        current.init(panelArgs)
        current.skin = cc.instantiate(panelPrefab)
        current.initDone()
        LayerMgr.setLayer(current.skin, AppConstants.viewLayer.Panel)
        this._panels.set(viewName, current)
        current.skin.active = false
        current.showing()
        this.startShowPanel(current, current.panelShowStyle, true)
    }
    // 隐藏 Panel
    public static hide(panelName: string) {
        if (!this._panels.has(panelName)) {
            console.error(`PanelMgr.hide 面板[${panelName}]不存在`)
            return
        }
        const pb = this._panels.get(panelName)
        if (!pb.skin.active) {
            console.error(`PanelMgr.hide 面板[${panelName}]已隐藏`)
            return
        }
        TopBlock.show()
        this.startShowPanel(pb, pb.panelShowStyle, false)
    }
    // 销毁 Panel
    public static destroy(panelName: string) {
        if (!this._panels.has(panelName)) {
            console.error(`PanelMgr.destroy 面板[${panelName}]不存在`)
            return
        }
        let pb = this._panels.get(panelName)
        pb.hiding()
        pb.skin.active = false
        pb.hided()
        this._panels.delete(panelName)
        pb.destroy()
        pb = null
    }
    private static startShowPanel(go: PanelBase, showStyle: number, isOpen: boolean) {
        switch (showStyle) {
            case AppConstants.panelShowStyle.Normal:
                this.showNormal(go, isOpen)
                break
        }
    }
    //#region 显示方式
    /** 默认显示 */
    private static showNormal(go: PanelBase, isOpen: boolean) {
        if (isOpen) {
            go.skin.active = true
            go.showed()
        } else {
            this.destroy(go.panelName)
        }
        this.showPanelAfter()
    }
    //#endregion
    private static showPanelAfter() {
        TopBlock.hide()
    }
}
参考UIMain,创建一个新的PanelYellow,创建一个名为BtnClose文本为关闭的按钮,然后把 PanelYellow节点拖动到resources目录下并从场景删除。

新建scripts/PanelYellow.ts,内容如下。
import AppUtil from "../framework/scripts/AppUtil"
import PanelBase from "../framework/scripts/view/PanelBase"
import PanelMgr from "../framework/scripts/view/PanelMgr"
export default class PanelYellow extends PanelBase {
    public skinPath: string = 'PanelYellow'
    protected onButtonClick(button: cc.Node) {
        if (button.name == 'BtnClose') {
            PanelMgr.hide(AppUtil.getClassName(PanelYellow))
        }
    }
}
编辑UIMain界面,创建一个名为BtnPanelYellow文本为黄面板的按钮。

编辑scripts/UIMain.ts, onButtonClick方法添加如下代码。
case 'BtnPanelYellow':
    PanelMgr.show(PanelYellow)
    break
运行程序,点击黄面板按钮,打开PanelYellow界面,然后点击关闭按钮,也能正确关闭面板。虽然面板的打开和关闭都正常了,但还存在两个问题,一是PanelMgr.hide(AppUtil.getClassName(PanelYellow))这行代码多了AppUtil.getClassName这一步调用比较繁琐,二是打开面板后还能点击黄色面板区域以外的按钮。我们先解决第一个问题,第二个问题下个章节处理。
编辑framework/scripts/view/PanelBase.ts,添加close和closeImmediate方法。
// 关闭面板(有动画)
public close() {
    PanelMgr.hide(this.panelName)
}
// 关闭面板(无动画, 立即关闭)
public closeImmediate() {
    PanelMgr.destroy(this.panelName)
}
编辑scripts/PanelYellow.ts,修改PanelMgr.hide(AppUtil.getClassName(PanelYellow))这一行为this.close(),再次运行程序,一样能正确关闭面板。也可以试下改成this.closeImmediate()关闭面板,发现是一样的效果,因为目前面板打开和关闭就是设置面板为true或者false。
本作品采用《CC 协议》,转载必须注明作者和本文链接
          
          
          
                关于 LearnKu
              
                    
                    
                    
 
推荐文章: