@eva/plugin-renderer-text 2.0.1-beta.27 → 2.0.1-beta.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -39,13 +39,66 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 文本组件(基于 PixiJS Text)
|
|
44
|
+
*
|
|
45
|
+
* Text 组件用于渲染文本内容,支持丰富的文本样式配置。
|
|
46
|
+
* 它基于 PixiJS 的 Text 实现,支持字体、颜色、描边、阴影、对齐等多种样式。
|
|
47
|
+
*
|
|
48
|
+
* 主要特性:
|
|
49
|
+
* - 支持多种字体和字号
|
|
50
|
+
* - 支持文本颜色、渐变填充
|
|
51
|
+
* - 支持描边和投影效果
|
|
52
|
+
* - 支持文本对齐和换行
|
|
53
|
+
* - 可配置渲染分辨率
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* // 基础文本
|
|
58
|
+
* const label = new GameObject('label');
|
|
59
|
+
* label.addComponent(new Text({
|
|
60
|
+
* text: 'Hello EVA!',
|
|
61
|
+
* style: {
|
|
62
|
+
* fontSize: 32,
|
|
63
|
+
* fill: 0xffffff
|
|
64
|
+
* }
|
|
65
|
+
* }));
|
|
66
|
+
*
|
|
67
|
+
* // 带样式的文本
|
|
68
|
+
* label.addComponent(new Text({
|
|
69
|
+
* text: '得分: 9999',
|
|
70
|
+
* style: {
|
|
71
|
+
* fontFamily: 'Arial',
|
|
72
|
+
* fontSize: 48,
|
|
73
|
+
* fontWeight: 'bold',
|
|
74
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
75
|
+
* stroke: '#000000',
|
|
76
|
+
* strokeThickness: 4,
|
|
77
|
+
* dropShadow: true,
|
|
78
|
+
* dropShadowDistance: 3
|
|
79
|
+
* },
|
|
80
|
+
* resolution: 2 // 高清渲染
|
|
81
|
+
* }));
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
42
84
|
class Text$2 extends eva_js.Component {
|
|
43
85
|
constructor() {
|
|
44
86
|
super(...arguments);
|
|
87
|
+
/** 文本内容 */
|
|
45
88
|
this.text = '';
|
|
89
|
+
/** 文本样式配置 */
|
|
90
|
+
// @decorators.IDEProp 复杂编辑后续添加
|
|
46
91
|
this.style = {};
|
|
92
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
47
93
|
this.resolution = 1;
|
|
48
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* 初始化组件
|
|
97
|
+
* @param obj - 初始化参数
|
|
98
|
+
* @param obj.text - 文本内容
|
|
99
|
+
* @param obj.style - 文本样式
|
|
100
|
+
* @param obj.resolution - 渲染分辨率
|
|
101
|
+
*/
|
|
49
102
|
init(obj) {
|
|
50
103
|
const style = new pixi_js.TextStyle({
|
|
51
104
|
fontSize: 20,
|
|
@@ -67,6 +120,7 @@ class Text$2 extends eva_js.Component {
|
|
|
67
120
|
}
|
|
68
121
|
}
|
|
69
122
|
}
|
|
123
|
+
/** 组件名称 */
|
|
70
124
|
Text$2.componentName = 'Text';
|
|
71
125
|
__decorate([
|
|
72
126
|
inspectorDecorator.type('string')
|
|
@@ -75,13 +129,84 @@ __decorate([
|
|
|
75
129
|
inspectorDecorator.type('number')
|
|
76
130
|
], Text$2.prototype, "resolution", void 0);
|
|
77
131
|
|
|
132
|
+
/**
|
|
133
|
+
* HTML 富文本组件
|
|
134
|
+
*
|
|
135
|
+
* HTMLText 组件支持渲染带有 HTML 标签的富文本内容。
|
|
136
|
+
* 可以在文本中使用 HTML 标签(如 `<b>`, `<i>`, `<span>` 等)来实现丰富的文本样式,
|
|
137
|
+
* 适用于聊天对话、新闻内容、富文本显示等需要多样式文本的场景。
|
|
138
|
+
*
|
|
139
|
+
* 支持的 HTML 标签:
|
|
140
|
+
* - `<b>` - 粗体
|
|
141
|
+
* - `<i>` - 斜体
|
|
142
|
+
* - `<span style="color:#ff0000">` - 自定义样式
|
|
143
|
+
* - `<br>` - 换行
|
|
144
|
+
* 以及更多标准 HTML 文本标签
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* // 基础富文本
|
|
149
|
+
* const label = new GameObject('label');
|
|
150
|
+
* label.addComponent(new HTMLText({
|
|
151
|
+
* text: '这是<b>粗体</b>和<i>斜体</i>文本',
|
|
152
|
+
* style: {
|
|
153
|
+
* fontSize: 24,
|
|
154
|
+
* fill: '#000000',
|
|
155
|
+
* fontFamily: 'Arial'
|
|
156
|
+
* }
|
|
157
|
+
* }));
|
|
158
|
+
*
|
|
159
|
+
* // 带颜色的富文本
|
|
160
|
+
* label.addComponent(new HTMLText({
|
|
161
|
+
* text: '欢迎 <span style="color:#ff0000">玩家123</span> 加入游戏!',
|
|
162
|
+
* style: {
|
|
163
|
+
* fontSize: 20,
|
|
164
|
+
* wordWrap: true,
|
|
165
|
+
* wordWrapWidth: 300
|
|
166
|
+
* }
|
|
167
|
+
* }));
|
|
168
|
+
*
|
|
169
|
+
* // 自定义标签样式
|
|
170
|
+
* label.addComponent(new HTMLText({
|
|
171
|
+
* text: '获得 <gold>100</gold> 金币',
|
|
172
|
+
* style: {
|
|
173
|
+
* fontSize: 18,
|
|
174
|
+
* tagStyles: {
|
|
175
|
+
* gold: {
|
|
176
|
+
* fill: '#ffd700',
|
|
177
|
+
* fontWeight: 'bold'
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
* }
|
|
181
|
+
* }));
|
|
182
|
+
*
|
|
183
|
+
* // 高分辨率渲染
|
|
184
|
+
* label.addComponent(new HTMLText({
|
|
185
|
+
* text: '高清文本',
|
|
186
|
+
* textureStyle: {
|
|
187
|
+
* resolution: 2,
|
|
188
|
+
* scaleMode: 'linear'
|
|
189
|
+
* }
|
|
190
|
+
* }));
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
78
193
|
class HTMLText extends eva_js.Component {
|
|
79
194
|
constructor() {
|
|
80
195
|
super(...arguments);
|
|
196
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
81
197
|
this.text = '';
|
|
198
|
+
/** 文本样式配置 */
|
|
82
199
|
this.style = {};
|
|
200
|
+
/** 纹理渲染配置 */
|
|
83
201
|
this.textureStyle = {};
|
|
84
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* 初始化组件
|
|
205
|
+
* @param obj - 初始化参数
|
|
206
|
+
* @param obj.text - 富文本内容
|
|
207
|
+
* @param obj.style - 文本样式
|
|
208
|
+
* @param obj.textureStyle - 纹理配置
|
|
209
|
+
*/
|
|
85
210
|
init(obj) {
|
|
86
211
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
87
212
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -90,6 +215,7 @@ class HTMLText extends eva_js.Component {
|
|
|
90
215
|
}
|
|
91
216
|
}
|
|
92
217
|
}
|
|
218
|
+
/** 组件名称 */
|
|
93
219
|
HTMLText.componentName = 'HTMLText';
|
|
94
220
|
__decorate([
|
|
95
221
|
inspectorDecorator.type('string')
|
|
@@ -127,6 +253,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
127
253
|
}
|
|
128
254
|
else {
|
|
129
255
|
this.change(changed);
|
|
256
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
130
257
|
const component = changed.component;
|
|
131
258
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
132
259
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -139,11 +266,13 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
139
266
|
addTextComponent(changed) {
|
|
140
267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
141
268
|
const component = changed.component;
|
|
269
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
142
270
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
143
271
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
144
272
|
delete styleWithoutFont.fontFamily;
|
|
145
273
|
const initialText = fontFamily ? '' : component.text;
|
|
146
274
|
const text = new rendererAdapter.Text(initialText, styleWithoutFont);
|
|
275
|
+
// 设置 resolution 以提升清晰度
|
|
147
276
|
if (component.resolution !== undefined && component.resolution > 0) {
|
|
148
277
|
text.resolution = component.resolution;
|
|
149
278
|
}
|
|
@@ -152,6 +281,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
152
281
|
text,
|
|
153
282
|
component,
|
|
154
283
|
};
|
|
284
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
155
285
|
if (fontFamily) {
|
|
156
286
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
157
287
|
}
|
|
@@ -160,6 +290,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
160
290
|
addHTMLTextComponent(changed) {
|
|
161
291
|
return __awaiter(this, void 0, void 0, function* () {
|
|
162
292
|
const component = changed.component;
|
|
293
|
+
// 创建样式副本,先不设置 fontFamily
|
|
163
294
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
164
295
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
165
296
|
delete styleWithoutFont.fontFamily;
|
|
@@ -170,11 +301,15 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
170
301
|
text: htmlText,
|
|
171
302
|
component,
|
|
172
303
|
};
|
|
304
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
173
305
|
if (fontFamily) {
|
|
174
306
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
175
307
|
}
|
|
176
308
|
});
|
|
177
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* 等待字体资源加载完成并更新文本
|
|
312
|
+
*/
|
|
178
313
|
waitForFontResource(text, changed, fontFamily) {
|
|
179
314
|
return __awaiter(this, void 0, void 0, function* () {
|
|
180
315
|
if (!fontFamily) {
|
|
@@ -182,13 +317,17 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
182
317
|
}
|
|
183
318
|
try {
|
|
184
319
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
320
|
+
// 通过 resource 系统获取字体资源
|
|
185
321
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
186
322
|
yield eva_js.resource.getResource(fontName);
|
|
323
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
187
324
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
188
325
|
return;
|
|
326
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
189
327
|
const component = this.texts[changed.gameObject.id].component;
|
|
190
328
|
text.style.fontFamily = fontFamily;
|
|
191
329
|
text.text = component.text;
|
|
330
|
+
// 更新尺寸
|
|
192
331
|
}
|
|
193
332
|
catch (error) {
|
|
194
333
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -205,12 +344,14 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
205
344
|
Object.assign(text.style, component.style);
|
|
206
345
|
}
|
|
207
346
|
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
347
|
+
// 更新 resolution
|
|
208
348
|
const textComponent = component;
|
|
209
349
|
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
210
350
|
text.resolution = textComponent.resolution;
|
|
211
351
|
}
|
|
212
352
|
}
|
|
213
353
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
354
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
214
355
|
const htmlComponent = component;
|
|
215
356
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
216
357
|
const index = container.getChildIndex(text);
|
|
@@ -13,11 +13,83 @@ import { TextStyleFontWeight } from 'pixi.js';
|
|
|
13
13
|
import { TextStyleTextBaseline } from 'pixi.js';
|
|
14
14
|
import { TextStyleWhiteSpace } from 'pixi.js';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* HTML 富文本组件
|
|
18
|
+
*
|
|
19
|
+
* HTMLText 组件支持渲染带有 HTML 标签的富文本内容。
|
|
20
|
+
* 可以在文本中使用 HTML 标签(如 `<b>`, `<i>`, `<span>` 等)来实现丰富的文本样式,
|
|
21
|
+
* 适用于聊天对话、新闻内容、富文本显示等需要多样式文本的场景。
|
|
22
|
+
*
|
|
23
|
+
* 支持的 HTML 标签:
|
|
24
|
+
* - `<b>` - 粗体
|
|
25
|
+
* - `<i>` - 斜体
|
|
26
|
+
* - `<span style="color:#ff0000">` - 自定义样式
|
|
27
|
+
* - `<br>` - 换行
|
|
28
|
+
* 以及更多标准 HTML 文本标签
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // 基础富文本
|
|
33
|
+
* const label = new GameObject('label');
|
|
34
|
+
* label.addComponent(new HTMLText({
|
|
35
|
+
* text: '这是<b>粗体</b>和<i>斜体</i>文本',
|
|
36
|
+
* style: {
|
|
37
|
+
* fontSize: 24,
|
|
38
|
+
* fill: '#000000',
|
|
39
|
+
* fontFamily: 'Arial'
|
|
40
|
+
* }
|
|
41
|
+
* }));
|
|
42
|
+
*
|
|
43
|
+
* // 带颜色的富文本
|
|
44
|
+
* label.addComponent(new HTMLText({
|
|
45
|
+
* text: '欢迎 <span style="color:#ff0000">玩家123</span> 加入游戏!',
|
|
46
|
+
* style: {
|
|
47
|
+
* fontSize: 20,
|
|
48
|
+
* wordWrap: true,
|
|
49
|
+
* wordWrapWidth: 300
|
|
50
|
+
* }
|
|
51
|
+
* }));
|
|
52
|
+
*
|
|
53
|
+
* // 自定义标签样式
|
|
54
|
+
* label.addComponent(new HTMLText({
|
|
55
|
+
* text: '获得 <gold>100</gold> 金币',
|
|
56
|
+
* style: {
|
|
57
|
+
* fontSize: 18,
|
|
58
|
+
* tagStyles: {
|
|
59
|
+
* gold: {
|
|
60
|
+
* fill: '#ffd700',
|
|
61
|
+
* fontWeight: 'bold'
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* }));
|
|
66
|
+
*
|
|
67
|
+
* // 高分辨率渲染
|
|
68
|
+
* label.addComponent(new HTMLText({
|
|
69
|
+
* text: '高清文本',
|
|
70
|
+
* textureStyle: {
|
|
71
|
+
* resolution: 2,
|
|
72
|
+
* scaleMode: 'linear'
|
|
73
|
+
* }
|
|
74
|
+
* }));
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
16
77
|
export declare class HTMLText extends Component<HTMLTextParams> {
|
|
78
|
+
/** 组件名称 */
|
|
17
79
|
static componentName: string;
|
|
80
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
18
81
|
text: string;
|
|
82
|
+
/** 文本样式配置 */
|
|
19
83
|
style: HTMLTextParams['style'];
|
|
84
|
+
/** 纹理渲染配置 */
|
|
20
85
|
textureStyle: HTMLTextParams['textureStyle'];
|
|
86
|
+
/**
|
|
87
|
+
* 初始化组件
|
|
88
|
+
* @param obj - 初始化参数
|
|
89
|
+
* @param obj.text - 富文本内容
|
|
90
|
+
* @param obj.style - 文本样式
|
|
91
|
+
* @param obj.textureStyle - 纹理配置
|
|
92
|
+
*/
|
|
21
93
|
init(obj?: HTMLTextParams): void;
|
|
22
94
|
}
|
|
23
95
|
|
|
@@ -60,11 +132,64 @@ declare interface HTMLTextStyleOptions {
|
|
|
60
132
|
whiteSpace?: string;
|
|
61
133
|
}
|
|
62
134
|
|
|
135
|
+
/**
|
|
136
|
+
* 文本组件(基于 PixiJS Text)
|
|
137
|
+
*
|
|
138
|
+
* Text 组件用于渲染文本内容,支持丰富的文本样式配置。
|
|
139
|
+
* 它基于 PixiJS 的 Text 实现,支持字体、颜色、描边、阴影、对齐等多种样式。
|
|
140
|
+
*
|
|
141
|
+
* 主要特性:
|
|
142
|
+
* - 支持多种字体和字号
|
|
143
|
+
* - 支持文本颜色、渐变填充
|
|
144
|
+
* - 支持描边和投影效果
|
|
145
|
+
* - 支持文本对齐和换行
|
|
146
|
+
* - 可配置渲染分辨率
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* // 基础文本
|
|
151
|
+
* const label = new GameObject('label');
|
|
152
|
+
* label.addComponent(new Text({
|
|
153
|
+
* text: 'Hello EVA!',
|
|
154
|
+
* style: {
|
|
155
|
+
* fontSize: 32,
|
|
156
|
+
* fill: 0xffffff
|
|
157
|
+
* }
|
|
158
|
+
* }));
|
|
159
|
+
*
|
|
160
|
+
* // 带样式的文本
|
|
161
|
+
* label.addComponent(new Text({
|
|
162
|
+
* text: '得分: 9999',
|
|
163
|
+
* style: {
|
|
164
|
+
* fontFamily: 'Arial',
|
|
165
|
+
* fontSize: 48,
|
|
166
|
+
* fontWeight: 'bold',
|
|
167
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
168
|
+
* stroke: '#000000',
|
|
169
|
+
* strokeThickness: 4,
|
|
170
|
+
* dropShadow: true,
|
|
171
|
+
* dropShadowDistance: 3
|
|
172
|
+
* },
|
|
173
|
+
* resolution: 2 // 高清渲染
|
|
174
|
+
* }));
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
63
177
|
declare class Text_2 extends Component<TextParams> {
|
|
178
|
+
/** 组件名称 */
|
|
64
179
|
static componentName: string;
|
|
180
|
+
/** 文本内容 */
|
|
65
181
|
text: string;
|
|
182
|
+
/** 文本样式配置 */
|
|
66
183
|
style: TextParams['style'];
|
|
184
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
67
185
|
resolution: number;
|
|
186
|
+
/**
|
|
187
|
+
* 初始化组件
|
|
188
|
+
* @param obj - 初始化参数
|
|
189
|
+
* @param obj.text - 文本内容
|
|
190
|
+
* @param obj.style - 文本样式
|
|
191
|
+
* @param obj.resolution - 渲染分辨率
|
|
192
|
+
*/
|
|
68
193
|
init(obj?: TextParams): void;
|
|
69
194
|
}
|
|
70
195
|
export { Text_2 as Text }
|
|
@@ -121,6 +246,9 @@ export declare class TextSystem extends Renderer {
|
|
|
121
246
|
componentChanged(changed: ComponentChanged): Promise<void>;
|
|
122
247
|
private addTextComponent;
|
|
123
248
|
private addHTMLTextComponent;
|
|
249
|
+
/**
|
|
250
|
+
* 等待字体资源加载完成并更新文本
|
|
251
|
+
*/
|
|
124
252
|
private waitForFontResource;
|
|
125
253
|
change(changed: ComponentChanged): void;
|
|
126
254
|
setSize(changed: ComponentChanged): void;
|
|
@@ -35,13 +35,66 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* 文本组件(基于 PixiJS Text)
|
|
40
|
+
*
|
|
41
|
+
* Text 组件用于渲染文本内容,支持丰富的文本样式配置。
|
|
42
|
+
* 它基于 PixiJS 的 Text 实现,支持字体、颜色、描边、阴影、对齐等多种样式。
|
|
43
|
+
*
|
|
44
|
+
* 主要特性:
|
|
45
|
+
* - 支持多种字体和字号
|
|
46
|
+
* - 支持文本颜色、渐变填充
|
|
47
|
+
* - 支持描边和投影效果
|
|
48
|
+
* - 支持文本对齐和换行
|
|
49
|
+
* - 可配置渲染分辨率
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* // 基础文本
|
|
54
|
+
* const label = new GameObject('label');
|
|
55
|
+
* label.addComponent(new Text({
|
|
56
|
+
* text: 'Hello EVA!',
|
|
57
|
+
* style: {
|
|
58
|
+
* fontSize: 32,
|
|
59
|
+
* fill: 0xffffff
|
|
60
|
+
* }
|
|
61
|
+
* }));
|
|
62
|
+
*
|
|
63
|
+
* // 带样式的文本
|
|
64
|
+
* label.addComponent(new Text({
|
|
65
|
+
* text: '得分: 9999',
|
|
66
|
+
* style: {
|
|
67
|
+
* fontFamily: 'Arial',
|
|
68
|
+
* fontSize: 48,
|
|
69
|
+
* fontWeight: 'bold',
|
|
70
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
71
|
+
* stroke: '#000000',
|
|
72
|
+
* strokeThickness: 4,
|
|
73
|
+
* dropShadow: true,
|
|
74
|
+
* dropShadowDistance: 3
|
|
75
|
+
* },
|
|
76
|
+
* resolution: 2 // 高清渲染
|
|
77
|
+
* }));
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
38
80
|
class Text$2 extends Component {
|
|
39
81
|
constructor() {
|
|
40
82
|
super(...arguments);
|
|
83
|
+
/** 文本内容 */
|
|
41
84
|
this.text = '';
|
|
85
|
+
/** 文本样式配置 */
|
|
86
|
+
// @decorators.IDEProp 复杂编辑后续添加
|
|
42
87
|
this.style = {};
|
|
88
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
43
89
|
this.resolution = 1;
|
|
44
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* 初始化组件
|
|
93
|
+
* @param obj - 初始化参数
|
|
94
|
+
* @param obj.text - 文本内容
|
|
95
|
+
* @param obj.style - 文本样式
|
|
96
|
+
* @param obj.resolution - 渲染分辨率
|
|
97
|
+
*/
|
|
45
98
|
init(obj) {
|
|
46
99
|
const style = new TextStyle({
|
|
47
100
|
fontSize: 20,
|
|
@@ -63,6 +116,7 @@ class Text$2 extends Component {
|
|
|
63
116
|
}
|
|
64
117
|
}
|
|
65
118
|
}
|
|
119
|
+
/** 组件名称 */
|
|
66
120
|
Text$2.componentName = 'Text';
|
|
67
121
|
__decorate([
|
|
68
122
|
type('string')
|
|
@@ -71,13 +125,84 @@ __decorate([
|
|
|
71
125
|
type('number')
|
|
72
126
|
], Text$2.prototype, "resolution", void 0);
|
|
73
127
|
|
|
128
|
+
/**
|
|
129
|
+
* HTML 富文本组件
|
|
130
|
+
*
|
|
131
|
+
* HTMLText 组件支持渲染带有 HTML 标签的富文本内容。
|
|
132
|
+
* 可以在文本中使用 HTML 标签(如 `<b>`, `<i>`, `<span>` 等)来实现丰富的文本样式,
|
|
133
|
+
* 适用于聊天对话、新闻内容、富文本显示等需要多样式文本的场景。
|
|
134
|
+
*
|
|
135
|
+
* 支持的 HTML 标签:
|
|
136
|
+
* - `<b>` - 粗体
|
|
137
|
+
* - `<i>` - 斜体
|
|
138
|
+
* - `<span style="color:#ff0000">` - 自定义样式
|
|
139
|
+
* - `<br>` - 换行
|
|
140
|
+
* 以及更多标准 HTML 文本标签
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // 基础富文本
|
|
145
|
+
* const label = new GameObject('label');
|
|
146
|
+
* label.addComponent(new HTMLText({
|
|
147
|
+
* text: '这是<b>粗体</b>和<i>斜体</i>文本',
|
|
148
|
+
* style: {
|
|
149
|
+
* fontSize: 24,
|
|
150
|
+
* fill: '#000000',
|
|
151
|
+
* fontFamily: 'Arial'
|
|
152
|
+
* }
|
|
153
|
+
* }));
|
|
154
|
+
*
|
|
155
|
+
* // 带颜色的富文本
|
|
156
|
+
* label.addComponent(new HTMLText({
|
|
157
|
+
* text: '欢迎 <span style="color:#ff0000">玩家123</span> 加入游戏!',
|
|
158
|
+
* style: {
|
|
159
|
+
* fontSize: 20,
|
|
160
|
+
* wordWrap: true,
|
|
161
|
+
* wordWrapWidth: 300
|
|
162
|
+
* }
|
|
163
|
+
* }));
|
|
164
|
+
*
|
|
165
|
+
* // 自定义标签样式
|
|
166
|
+
* label.addComponent(new HTMLText({
|
|
167
|
+
* text: '获得 <gold>100</gold> 金币',
|
|
168
|
+
* style: {
|
|
169
|
+
* fontSize: 18,
|
|
170
|
+
* tagStyles: {
|
|
171
|
+
* gold: {
|
|
172
|
+
* fill: '#ffd700',
|
|
173
|
+
* fontWeight: 'bold'
|
|
174
|
+
* }
|
|
175
|
+
* }
|
|
176
|
+
* }
|
|
177
|
+
* }));
|
|
178
|
+
*
|
|
179
|
+
* // 高分辨率渲染
|
|
180
|
+
* label.addComponent(new HTMLText({
|
|
181
|
+
* text: '高清文本',
|
|
182
|
+
* textureStyle: {
|
|
183
|
+
* resolution: 2,
|
|
184
|
+
* scaleMode: 'linear'
|
|
185
|
+
* }
|
|
186
|
+
* }));
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
74
189
|
class HTMLText extends Component {
|
|
75
190
|
constructor() {
|
|
76
191
|
super(...arguments);
|
|
192
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
77
193
|
this.text = '';
|
|
194
|
+
/** 文本样式配置 */
|
|
78
195
|
this.style = {};
|
|
196
|
+
/** 纹理渲染配置 */
|
|
79
197
|
this.textureStyle = {};
|
|
80
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* 初始化组件
|
|
201
|
+
* @param obj - 初始化参数
|
|
202
|
+
* @param obj.text - 富文本内容
|
|
203
|
+
* @param obj.style - 文本样式
|
|
204
|
+
* @param obj.textureStyle - 纹理配置
|
|
205
|
+
*/
|
|
81
206
|
init(obj) {
|
|
82
207
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
83
208
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -86,6 +211,7 @@ class HTMLText extends Component {
|
|
|
86
211
|
}
|
|
87
212
|
}
|
|
88
213
|
}
|
|
214
|
+
/** 组件名称 */
|
|
89
215
|
HTMLText.componentName = 'HTMLText';
|
|
90
216
|
__decorate([
|
|
91
217
|
type('string')
|
|
@@ -123,6 +249,7 @@ let Text = class Text extends Renderer {
|
|
|
123
249
|
}
|
|
124
250
|
else {
|
|
125
251
|
this.change(changed);
|
|
252
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
126
253
|
const component = changed.component;
|
|
127
254
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
128
255
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -135,11 +262,13 @@ let Text = class Text extends Renderer {
|
|
|
135
262
|
addTextComponent(changed) {
|
|
136
263
|
return __awaiter(this, void 0, void 0, function* () {
|
|
137
264
|
const component = changed.component;
|
|
265
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
138
266
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
139
267
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
140
268
|
delete styleWithoutFont.fontFamily;
|
|
141
269
|
const initialText = fontFamily ? '' : component.text;
|
|
142
270
|
const text = new Text$3(initialText, styleWithoutFont);
|
|
271
|
+
// 设置 resolution 以提升清晰度
|
|
143
272
|
if (component.resolution !== undefined && component.resolution > 0) {
|
|
144
273
|
text.resolution = component.resolution;
|
|
145
274
|
}
|
|
@@ -148,6 +277,7 @@ let Text = class Text extends Renderer {
|
|
|
148
277
|
text,
|
|
149
278
|
component,
|
|
150
279
|
};
|
|
280
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
151
281
|
if (fontFamily) {
|
|
152
282
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
153
283
|
}
|
|
@@ -156,6 +286,7 @@ let Text = class Text extends Renderer {
|
|
|
156
286
|
addHTMLTextComponent(changed) {
|
|
157
287
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
288
|
const component = changed.component;
|
|
289
|
+
// 创建样式副本,先不设置 fontFamily
|
|
159
290
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
160
291
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
161
292
|
delete styleWithoutFont.fontFamily;
|
|
@@ -166,11 +297,15 @@ let Text = class Text extends Renderer {
|
|
|
166
297
|
text: htmlText,
|
|
167
298
|
component,
|
|
168
299
|
};
|
|
300
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
169
301
|
if (fontFamily) {
|
|
170
302
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
171
303
|
}
|
|
172
304
|
});
|
|
173
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* 等待字体资源加载完成并更新文本
|
|
308
|
+
*/
|
|
174
309
|
waitForFontResource(text, changed, fontFamily) {
|
|
175
310
|
return __awaiter(this, void 0, void 0, function* () {
|
|
176
311
|
if (!fontFamily) {
|
|
@@ -178,13 +313,17 @@ let Text = class Text extends Renderer {
|
|
|
178
313
|
}
|
|
179
314
|
try {
|
|
180
315
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
316
|
+
// 通过 resource 系统获取字体资源
|
|
181
317
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
182
318
|
yield resource.getResource(fontName);
|
|
319
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
183
320
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
184
321
|
return;
|
|
322
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
185
323
|
const component = this.texts[changed.gameObject.id].component;
|
|
186
324
|
text.style.fontFamily = fontFamily;
|
|
187
325
|
text.text = component.text;
|
|
326
|
+
// 更新尺寸
|
|
188
327
|
}
|
|
189
328
|
catch (error) {
|
|
190
329
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -201,12 +340,14 @@ let Text = class Text extends Renderer {
|
|
|
201
340
|
Object.assign(text.style, component.style);
|
|
202
341
|
}
|
|
203
342
|
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
343
|
+
// 更新 resolution
|
|
204
344
|
const textComponent = component;
|
|
205
345
|
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
206
346
|
text.resolution = textComponent.resolution;
|
|
207
347
|
}
|
|
208
348
|
}
|
|
209
349
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
350
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
210
351
|
const htmlComponent = component;
|
|
211
352
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
212
353
|
const index = container.getChildIndex(text);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eva/plugin-renderer-text",
|
|
3
|
-
"version": "2.0.1-beta.
|
|
3
|
+
"version": "2.0.1-beta.28",
|
|
4
4
|
"description": "@eva/plugin-renderer-text",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/plugin-renderer-text.esm.js",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"homepage": "https://eva.js.org",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@eva/inspector-decorator": "^0.0.5",
|
|
22
|
-
"@eva/plugin-renderer": "2.0.1-beta.
|
|
23
|
-
"@eva/renderer-adapter": "2.0.1-beta.
|
|
24
|
-
"@eva/eva.js": "2.0.1-beta.
|
|
22
|
+
"@eva/plugin-renderer": "2.0.1-beta.28",
|
|
23
|
+
"@eva/renderer-adapter": "2.0.1-beta.28",
|
|
24
|
+
"@eva/eva.js": "2.0.1-beta.28",
|
|
25
25
|
"pixi.js": "^8.8.1"
|
|
26
26
|
}
|
|
27
27
|
}
|