Skip to content

Commit 48b2fdf

Browse files
Update index.md
1 parent a5a8e29 commit 48b2fdf

File tree

1 file changed

+75
-3
lines changed

1 file changed

+75
-3
lines changed

blog/posts/rfc2/index.md

+75-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ tags: ['RFC']
77

88
第一次提交版本,2024年1月20日。
99

10+
第二次提交版本,2024年1月24日,更新了有关切换类名的指令、模板数据结构和具体的 CSS 替换实现方案的内容。
11+
1012
## 总体方案
1113

1214
WebGAL 将使用模板思想进行 UI 自定义。在 WebGAL Terre 编辑器中,额外添加一个模板编辑器。在创建 WebGAL 游戏时和创建 WebGAL 游戏后,可以选择要使用的模板。
@@ -19,6 +21,7 @@ WebGAL 将使用模板思想进行 UI 自定义。在 WebGAL Terre 编辑器中
1921

2022
```
2123
templateName/
24+
├── template.json
2225
├── assets/
2326
└── UI/
2427
└── Title/
@@ -27,6 +30,16 @@ templateName/
2730

2831
其中,`assets` 是资源目录。
2932

33+
模板的数据结构是:
34+
35+
```json
36+
{
37+
"name":"模板名称",
38+
"version":"4.4.10",
39+
"其他字段":"待定......"
40+
}
41+
```
42+
3043
### 模板配置文件定义
3144

3245
模板配置文件将覆盖 WebGAL 默认样式的一些类,通过动态创建 CSS 来实现。
@@ -65,6 +78,63 @@ useApplyStyle('UI/Title/title.css',{"Title_button":styles.Title_button});
6578

6679
这样就完成了对某个页面元素的 UI 自定义。
6780

81+
### 切换类名的指令
82+
83+
有时候,用户可能准备了多个类名以定义不同的样式,并希望使用脚本切换以达到某些表现效果。`applyStyle` 指令可以切换类名。
84+
85+
```
86+
; 将 Title_button 类切换到 Title_button_2 类
87+
applyStyle:Title_button->Title_button_2;
88+
; 可以同时应用多个切换
89+
applyStyle:Title_button->Title_button_2, Dialog->Dialog_1;
90+
```
91+
92+
### 实现方法概览
93+
94+
首先,在初始化模板时,WebGAL 维护一个从原始的模板中类名到 css module 生成的类名的映射:
95+
96+
```
97+
const styleMap = new Map<string,{targetClass:string, currentApplyClass:string}>();
98+
```
99+
100+
`targetClass` 代表要替换到的目标类名,比如 `styles.Title_button`(这是 css module 生成的,运行时会替换为一个随机字符串),`currentApplyClass` 代表目前应用的类名,在初始化时与模板默认类名保持一致,但是可以被 `applyStyle` 指令切换。
101+
102+
在注册时,就订阅类名切换的事件。如果某个插入的 css 段中的类名发生了“切换类名”,那么这个事件就会发出。指令会重新注册 `currentApplyClass`,然后清除原有的 css 段,并重新字符串替换后插入新的 css 段。
103+
104+
比如,原有的 `styleMap` 中有一个实体 `"Title_button"->{targetClass:styles.Title_button, currentApplyClass:"Title_button"}`
105+
106+
运行了指令`applyStyle:Title_button->Title_button_2;`
107+
108+
此时更新 Map,注册为 `Title_button"->{targetClass:styles.Title_button, currentApplyClass:"Title_button_2"}`
109+
110+
这时候,要替换到 `stytle.Title_button` 的类名就变为 `Title_button_2`,原有的 `Title_button` 由于不被替换,所以无法生效。
111+
112+
由此可见,切换类名的脚本要发出事件
113+
114+
```
115+
// ... 其他逻辑
116+
eventBus.emit('classname-change',类名)
117+
```
118+
119+
`useApplyStyle` 要接受事件并判断是否要重新替换 CSS:
120+
121+
```ts
122+
const useApplyStyle = (url:string,classNameMap:Record<string,string>) => {
123+
useEffect(()=>{
124+
const applyStyle = ()=>{
125+
// ...... 其他代码
126+
}
127+
eventBus.on('classname-change',className=>{
128+
const isHotReplace = Object.keys(classNameMap).findIndex(e === className) > -1;
129+
if(isHotReplace) applyStyle();
130+
})
131+
return ()=>{
132+
eventBus.off(......)
133+
}
134+
},[])
135+
}
136+
```
137+
68138
### 引用资源
69139

70140
如果一个模板要引用资源,必须引用在模板资源目录下的资源。
@@ -145,10 +215,12 @@ registerStyleEditor('UI/Title/title.css', "Title_button", t("标题按钮")) //
145215

146216
```ts
147217
const useApplyStyle = (url:string,classNameMap:Record<string,string>) => {
148-
const applyStyle = ()=>{
218+
useEffect(()=>{
219+
const applyStyle = ()=>{
149220
// ...... 其他代码
150-
}
151-
register(url, applyStyle);// 注册回调函数,当编辑器后端通知时,重新跑一遍 applyStyle
221+
}
222+
register(url, applyStyle);// 注册回调函数,当编辑器后端通知时,重新跑一遍 applyStyle
223+
},[])
152224
}
153225
```
154226

0 commit comments

Comments
 (0)