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.tsonButtonClick方法添加如下代码。

case 'BtnPanelYellow':
    PanelMgr.show(PanelYellow)
    break

运行程序,点击黄面板按钮,打开PanelYellow界面,然后点击关闭按钮,也能正确关闭面板。虽然面板的打开和关闭都正常了,但还存在两个问题,一是PanelMgr.hide(AppUtil.getClassName(PanelYellow))这行代码多了AppUtil.getClassName这一步调用比较繁琐,二是打开面板后还能点击黄色面板区域以外的按钮。我们先解决第一个问题,第二个问题下个章节处理。

编辑framework/scripts/view/PanelBase.ts,添加closecloseImmediate方法。

// 关闭面板(有动画)
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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!