laya fgui 超簡單的UI框架
阿新 • • 發佈:2021-06-21
FairyGUI 超簡單的UI框架
Laya使用fgui的超簡單UI框架
使用場景:用於使用fgui進行layaUI開發的程式人員
整個框架分為3個模組,共有4個類:
- FGUIManager :FGUI的管理類,繼承於IUIManager 負責所有UI的開啟關閉等事項
- FUIBase :UI的管理基類,具體實現
- IUIManager :FGUI的介面類 規定管理類的各個方法
- UILayerType: UI 層級分類
FGUIManager管理類
import IUIManager from "./IUIManager"; import { FUIBase } from "./FUIBase"; import GameEntry from "../../GameEntry"; /** * @ name:FGUIManager * @ desc:自動建立說明 * @ user:By NUOLO * @ data: 2021-06-02 18:14 */ export default class FGUIManager implements IUIManager { /** * */ constructor() { this.Init(); } Init(): void { Laya.stage.addChild(fgui.GRoot.inst.displayObject); //初始化FGUI this.UIroot = fgui.GRoot.inst.displayObject; this.UIroot.width = Laya.stage.width; this.UIroot.height = Laya.stage.height; fgui.UIConfig.packageFileExtension = "fui"; //設定匯出檔案的拓展名 程式碼預設的拓展名為fui,可能於自身匯出的拓展名不同 但最好這樣做因為有些平臺只認這種檔名 this.UIDic = {}; } /** * UI字典 */ UIDic: { [name: string]: FUIBase<fgui.GComponent>}; /** * UI的根節點 */ private UIroot: Laya.Sprite; /** * 注入FUIBase */ RigisterUIBase(name: string, ui: FUIBase<fgui.GComponent>): void { if (this.UIDic[name]) { console.log(name + "::欄位已存在UI介面,請勿重複新增") return; } else { this.UIDic[name] = ui; } } CreateOrOpenPanel(name: string, data?:new () => FUIBase<fgui.GComponent> , isCloseOther?: boolean): FUIBase<any> { if (!this.UIroot) { this.Init(); } if (this.UIDic[name]) { return this.OpenPanel(name, isCloseOther); } else { let cla = new data(); if (fgui.UIPackage.addPackage(data['ResName']) == null) { console.log('資源包未載入,將進行自動載入'); fgui.UIPackage.addPackage(data['ResName']); } // let com = fgui.UIPackage.createObject(data['UIpackName'], data['UIName'], cla.ClassType).asCom; let com = fgui.UIPackage.createObjectFromURL(cla.ClassType.URL,cla.ClassType).asCom ; com.name = data['UIName']; fgui.GRoot.inst.addChild(com); com.makeFullScreen(); com.sortingOrder = cla.LayerType; cla.MUI = com; cla.UIMgr = this; cla.AutoRigisterToUIManager(); cla.onAwake(); cla.onEnable(); return cla; } } OpenPanel(name: string, isCloseOther?: boolean): FUIBase<any> { if (isCloseOther) { for (let uiname in this.UIDic) { this.UIDic[uiname].Close(); } } if (this.UIDic[name]) { let ui = this.UIDic[name]; ui.Open(); return ui; } else { console.error(name + "::欄位在UI字典中不存在,請檢查是否有誤") return null; } } ClosePanel(name: string, toOpenWindow?: string): void { if (this.UIDic[name]) { let ui = this.UIDic[name]; ui.Close(); if (toOpenWindow != null) { this.OpenPanel(toOpenWindow); } } else { console.log(name + "::欄位在UI字典中不存在,請檢查是否有誤") } } CloseAllPanel(): void { for (const key in this.UIDic) { this.UIDic[key].Close(); } } GetUIPanel(name: string): any { if (this.UIDic[name]) { return this.UIDic[name] ; } else { console.log(name + "::欄位在Ui字典中不存在,請檢查") return null; } } DestoryUIPanel(name: string) { if (this.UIDic[name]) { this.UIDic[name].Destory(); } else { console.log(name + "::欄位在Ui字典中不存在,請檢查") } } }
FUIBase
import AssetData from "../../Asset/AssetData"; import Debug from "../../Debug/Debug"; import GameEntry from "../../GameEntry"; import IUIManager from "./IUIManager"; import { UILayerType } from "./UILayerType"; /** * @ name:FUIBase * @ desc:自動建立說明 * @ user:By NUOLO * @ data: 2021-06-02 16:24 */ export class FUIBase<T extends fgui.GComponent> { /**需子類設定 匯出包的路徑 */ public static ResName: string = "res/UIVSLoading"; /**需子類設定 圖集的數量 從0 開始 */ public static AtliasCount: number = 1; public static UIName: string = "1"; //UI的名字 要存在字典中 public get UIName(): string { return FUIBase.UIName; } public set UIName(v: string) { FUIBase.UIName = v; } /** UI的層級 預設0級為最底層 */ public LayerType: UILayerType = UILayerType.Normal; /**fgui 元件 */ private m_uiComPonent: T; public get MUI(): T { return this.m_uiComPonent; } public set MUI(v: T) { this.m_uiComPonent = v; } /**fgui 元件 */ public ClassType: any; /**UI管理類 */ private m_uimgr: IUIManager; public get UIMgr(): IUIManager { return this.m_uimgr; } public set UIMgr(v: IUIManager) { this.m_uimgr = v; } /** * 自動註冊進UIManager */ public AutoRigisterToUIManager() { this.UIMgr.RigisterUIBase(this.UIName, this); } /** * 開啟介面 */ public Open() { this.onEnable(); this.m_uiComPonent.visible = true; } /** * 關閉介面 */ public Close() { this.onDisable(); this.m_uiComPonent.visible = false; } /** * 銷燬介面 */ public Destory() { this.m_uiComPonent.dispose(); } //#region fgui載入 /** * 獲取當前介面所對應的資原始檔 * @returns */ public static GetLoadUIPackDic(): any[] { let urls = []; urls.push({ url: this.ResName + ".fui", type: Laya.Loader.BUFFER }); urls.push({ url: this.ResName + "_atlas0.png", type: Laya.Loader.IMAGE }); //載入紋理集 if (this.AtliasCount >=1) { for (let i = 1; i <= this.AtliasCount; i++) { urls.push({ url: this.ResName + "_atlas0_" + i + ".png", type: Laya.Loader.IMAGE }); } } return urls; } /** * 獲取FGUI 二進位制檔案路徑 * @returns 對應路徑 */ public static GetUIByte(): string { return this.ResName + ".fui"; } /** * 載入完成之後 將包新增到fgui包管理中 */ public static AddPackage() { fgui.UIPackage.addPackage(this.ResName); } //#endregion //#region 功能 /** * 獲得子節點 * @param path 路徑資訊 s.b.v */ public FindChild<T extends fgui.GObject>(path: String): T { return this.m_uiComPonent.getChildByPath(path) as T; } /** * 新增事件監聽 * @param btn 點選按鈕 * @param callback 回撥 * @param args 傳遞資料 */ public AddLinster(btn: fgui.GObject, callback, ...args) { btn.onClick(this, callback, args); } /** * 移除事件監聽 * @param btn 按鈕 * @param callback 回撥 */ public RemoveLinster(btn: fgui.GObject, callback) { btn.offClick(btn, callback); } //#endregion //#region 生命流程 onAwake() {} //onAwake 建立時呼叫 onEnable() {} //每次開啟時呼叫,可自行拓展開啟時的開啟效果等功能 onDisable() {} //每次關閉時呼叫,可自行拓展關閉時的 所需呼叫的功能 //#endregion }
IUIManager
import { FUIBase } from "./FUIBase"; /** * @ name:IUIManager * @ desc:UI管理類的介面 * @ user:By NUOLO * @ data: 2021-06-02 16:14 */ export default interface IUIManager { /** * 初始化 */ Init():void /** * UI字典 */ UIDic: { [name: string]: FUIBase<any> }; /** * 注入FUIBase */ RigisterUIBase(name: string, ui: FUIBase<any>): void; /** * 自動建立 或者開啟 介面 注意:建立UI是非同步操作的 * @param name 名字 * @param isCloseOther 是否關閉其他介面 * @param data 資料 */ CreateOrOpenPanel(name: string, data?:any, isCloseOther?: boolean ): FUIBase<any> /** * 開啟UI介面 * @param name 要開啟介面的名字 * @param isCloseOther 是否關閉其他介面 預設否 */ OpenPanel(name: string, isCloseOther?: boolean): FUIBase<any>; /** * 關閉UI介面 * @param name 要關閉UI介面的名字 * @param TOOpen 關閉此介面後要開啟的介面的名字 預設無 不開啟其他介面 */ ClosePanel(name: string,toOpenWindow?:string): void; /** * 關閉所有UI介面 */ CloseAllPanel(): void; /** * 根據識別符號獲取FUIBase * @param name 識別符號 */ GetUIPanel(name: string):any; /** * 銷燬UIPanel * @param name 識別符號 */ DestoryUIPanel(name: string); }
UILayerType
/**
* @ name:UILayerType
* @ desc:UI 層級分類
* @ user:By NUOLO
* @ data: 2021-06-02 16:55
*/
export enum UILayerType {
//普通窗體
Normal=0,
//固定窗體
Fixed=20,
//彈出窗體
PopUp = 50,
//提示窗體
Tip = 40,
}
框架就分為這4個類 使用的話就每個UI介面都繼承 FUIBase<具體fgui匯出的UI類>
並重寫 引數
如例子:
fgui 匯出檔案為 Package1.fui
Package1Binder.ts
UI_Component1.ts
Package1Binder.ts
新建一個ShowUI 的指令碼 繼承與FUIBase <UI_Component1>
示例 ShowUI類
import { FUIBase } from "../Core/UI/FGUI/FUIBase";
import { UILayerType } from "../Core/UI/FGUI/UILayerType";
import Package1Binder from "./Package1/Package1Binder";
import UI_Component1 from "./Package1/UI_Component1";
/**
* @ name:ShowUI
* @ desc:UI的控制類
* @ user:By NUOLO
* @ data: 2021-06-09 11:00
*/
export default class ShowUI extends FUIBase <UI_Component1>{
public static ResName: string = "res/FGUI/Package1"; //路徑
public static AtliasCount: number = 0; //圖集數量 從0開始
public static UIName: string = "1"; //名稱
constructor() {
super();
this.LayerType = UILayerType.Normal; //設定層級
this.ClassType = UI_Component1; //設定UI所對應的類,,確定好再填
Package1Binder.bindAll(); //UI繫結類
}
onAwake() {
super.onAwake();
}
onEnable() {
super.onEnable();
}
onDisable() {
super.onDisable();
}
}
示例 呼叫方法
onConfigLoaded(): void {
//載入IDE指定的場景
// GameConfig.startScene && Laya.Scene.open(GameConfig.startScene);
this.openFGUI();
}
openFGUI() {
let uimagr = new FGUIManager(); //初始化UI管理類
//開啟介面
Laya.loader.create(ShowUI.GetLoadUIPackDic(), Laya.Handler.create(this, () => {
uimagr.CreateOrOpenPanel(ShowUI.UIName, ShowUI);
}));
}
整個呼叫過程都很簡單,程式碼邏輯也很明瞭,自己正在使用中
如果有更好的方法和更優雅的寫法,也請通過郵件聯絡我,共同學習一下,多謝!
個人部落格地址 https://nuolo.xyz