@eva/plugin-renderer-text 2.0.1-beta.27 → 2.0.1-beta.29
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.
- package/dist/EVA.plugin.renderer.text.js +1 -14
- package/dist/EVA.plugin.renderer.text.min.js +1 -1
- package/dist/plugin-renderer-text.cjs.js +139 -18
- package/dist/plugin-renderer-text.cjs.prod.js +2 -2
- package/dist/plugin-renderer-text.d.ts +126 -2
- package/dist/plugin-renderer-text.esm.js +139 -18
- package/package.json +4 -4
|
@@ -60,7 +60,6 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
60
60
|
super(...arguments);
|
|
61
61
|
this.text = '';
|
|
62
62
|
this.style = {};
|
|
63
|
-
this.resolution = 1;
|
|
64
63
|
}
|
|
65
64
|
init(obj) {
|
|
66
65
|
const style = new pixi_js.TextStyle({
|
|
@@ -77,15 +76,11 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
77
76
|
if (obj) {
|
|
78
77
|
this.text = obj.text;
|
|
79
78
|
_extends(this.style, obj.style);
|
|
80
|
-
if (obj.resolution !== undefined) {
|
|
81
|
-
this.resolution = obj.resolution;
|
|
82
|
-
}
|
|
83
79
|
}
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
Text$2.componentName = 'Text';
|
|
87
83
|
__decorate([type('string')], Text$2.prototype, "text", void 0);
|
|
88
|
-
__decorate([type('number')], Text$2.prototype, "resolution", void 0);
|
|
89
84
|
class HTMLText extends eva_js.Component {
|
|
90
85
|
constructor() {
|
|
91
86
|
super(...arguments);
|
|
@@ -159,9 +154,6 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
159
154
|
delete styleWithoutFont.fontFamily;
|
|
160
155
|
const initialText = fontFamily ? '' : component.text;
|
|
161
156
|
const text = new rendererAdapter.Text(initialText, styleWithoutFont);
|
|
162
|
-
if (component.resolution !== undefined && component.resolution > 0) {
|
|
163
|
-
text.resolution = component.resolution;
|
|
164
|
-
}
|
|
165
157
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
166
158
|
this.texts[changed.gameObject.id] = {
|
|
167
159
|
text,
|
|
@@ -223,11 +215,6 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
223
215
|
text.text = component.text;
|
|
224
216
|
} else if (changed.prop.prop[0] === 'style') {
|
|
225
217
|
_extends(text.style, component.style);
|
|
226
|
-
} else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
227
|
-
const textComponent = component;
|
|
228
|
-
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
229
|
-
text.resolution = textComponent.resolution;
|
|
230
|
-
}
|
|
231
218
|
} else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
232
219
|
const htmlComponent = component;
|
|
233
220
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
@@ -263,7 +250,7 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
263
250
|
Text: ['text', {
|
|
264
251
|
prop: ['style'],
|
|
265
252
|
deep: true
|
|
266
|
-
}
|
|
253
|
+
}],
|
|
267
254
|
HTMLText: ['text', {
|
|
268
255
|
prop: ['style'],
|
|
269
256
|
deep: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function _extends(){return _extends=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var
|
|
1
|
+
function _extends(){return _extends=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)({}).hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t},_extends.apply(null,arguments)}globalThis.EVA=globalThis.EVA||{},globalThis.EVA.plugin=globalThis.EVA.plugin||{},globalThis.EVA.plugin.renderer=globalThis.EVA.plugin.renderer||{};var _EVA_IIFE_text=function(t,e,n,i,o){"use strict";function s(t,e,n,i){var o,s=arguments.length,r=s<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,n,i);else for(var c=t.length-1;c>=0;c--)(o=t[c])&&(r=(s<3?o(r):s>3?o(e,n,r):o(e,n))||r);return s>3&&r&&Object.defineProperty(e,n,r),r}function r(t,e,n,i){return new(n||(n=Promise))((function(o,s){function r(t){try{l(i.next(t))}catch(t){s(t)}}function c(t){try{l(i.throw(t))}catch(t){s(t)}}function l(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(r,c)}l((i=i.apply(t,e||[])).next())}))}function c(t){return function(e,n){var i=function(t,e){return t.constructor.IDEProps||(t.constructor.IDEProps={}),t.constructor.IDEProps[e]||(t.constructor.IDEProps[e]={}),t.constructor.IDEProps[e]}(e,n);i.key=n,i.type=t}}class l extends n.Component{constructor(){super(...arguments),this.text="",this.style={}}init(t){const n=new e.TextStyle({fontSize:20}),i={};for(const t in n)0===t.indexOf("_")&&(i[t.substring(1)]=n[t]);delete i.styleKey,this.style=i,t&&(this.text=t.text,_extends(this.style,t.style))}}l.componentName="Text",s([c("string")],l.prototype,"text",void 0);class a extends n.Component{constructor(){super(...arguments),this.text="",this.style={},this.textureStyle={}}init(t){this.style=_extends({fontSize:24,fill:"#000000",fontFamily:"Arial"},null==t?void 0:t.style),this.textureStyle=_extends({scaleMode:"linear",resolution:window.devicePixelRatio||1},null==t?void 0:t.textureStyle),t&&(this.text=t.text)}}a.componentName="HTMLText",s([c("string")],a.prototype,"text",void 0);let d=class extends i.Renderer{constructor(){super(...arguments),this.name="Text",this.texts={}}init(){this.renderSystem=this.game.getSystem(i.RendererSystem),this.renderSystem.rendererManager.register(this)}componentChanged(t){return r(this,void 0,void 0,(function*(){const e="Text"===t.componentName,i="HTMLText"===t.componentName;if(e||i)if(t.type===n.OBSERVER_TYPE.ADD)e?yield this.addTextComponent(t):yield this.addHTMLTextComponent(t),this.setSize(t);else if(t.type===n.OBSERVER_TYPE.REMOVE)this.containerManager.getContainer(t.gameObject.id).removeChild(this.texts[t.gameObject.id].text),this.texts[t.gameObject.id].text.destroy({children:!0}),delete this.texts[t.gameObject.id];else{this.change(t);const e=t.component;if("style"===t.prop.prop[0]&&e.style&&e.style.fontFamily){const{text:n}=this.texts[t.gameObject.id];yield this.waitForFontResource(n,t,e.style.fontFamily)}this.setSize(t)}}))}addTextComponent(t){return r(this,void 0,void 0,(function*(){const e=t.component,n=_extends({},e.style),i=n.fontFamily;delete n.fontFamily;const s=i?"":e.text,r=new o.Text(s,n);this.containerManager.getContainer(t.gameObject.id).addChildAt(r,0),this.texts[t.gameObject.id]={text:r,component:e},i&&(yield this.waitForFontResource(r,t,i))}))}addHTMLTextComponent(t){return r(this,void 0,void 0,(function*(){const e=t.component,n=_extends({},e.style),i=n.fontFamily;delete n.fontFamily;const s=i?"":e.text,r=new o.HTMLText(_extends({text:s,style:n},e.textureStyle&&{textureStyle:e.textureStyle}));this.containerManager.getContainer(t.gameObject.id).addChildAt(r,0),this.texts[t.gameObject.id]={text:r,component:e},i&&(yield this.waitForFontResource(r,t,i))}))}waitForFontResource(t,e,i){return r(this,void 0,void 0,(function*(){if(i)try{const o=Array.isArray(i)?i[0]:i,s=this.increaseAsyncId(e.gameObject.id);if(yield n.resource.getResource(o),!this.validateAsyncId(e.gameObject.id,s))return;const r=this.texts[e.gameObject.id].component;t.style.fontFamily=i,t.text=r.text}catch(t){console.warn(`字体资源 ${i} 加载失败:`,t)}}))}change(t){const{text:e,component:n}=this.texts[t.gameObject.id],i="HTMLText"===t.componentName;if("text"===t.prop.prop[0])e.text=n.text;else if("style"===t.prop.prop[0])_extends(e.style,n.style);else if("textureStyle"===t.prop.prop[0]&&i){const i=n,s=this.containerManager.getContainer(t.gameObject.id),r=s.getChildIndex(e);s.removeChild(e),e.destroy({children:!0});const c=new o.HTMLText({text:i.text,style:i.style,textureStyle:i.textureStyle});s.addChildAt(c,r),this.texts[t.gameObject.id].text=c}}setSize(t){const{transform:e}=t.gameObject;if(!e)return;const{text:n}=this.texts[t.gameObject.id],i=n.getSize();e.size.width=i.width,e.size.height=i.height}};d.systemName="Text",d=s([n.decorators.componentObserver({Text:["text",{prop:["style"],deep:!0}],HTMLText:["text",{prop:["style"],deep:!0},{prop:["textureStyle"],deep:!0}]})],d);var x=d;return t.HTMLText=a,t.Text=l,t.TextSystem=x,Object.defineProperty(t,"__esModule",{value:!0}),t}({},PIXI,EVA,EVA.plugin.renderer,EVA.rendererAdapter);globalThis.EVA.plugin.renderer.text=globalThis.EVA.plugin.renderer.text||_EVA_IIFE_text;
|
|
@@ -39,13 +39,63 @@ 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
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // 基础文本
|
|
57
|
+
* const label = new GameObject('label');
|
|
58
|
+
* label.addComponent(new Text({
|
|
59
|
+
* text: 'Hello EVA!',
|
|
60
|
+
* style: {
|
|
61
|
+
* fontSize: 32,
|
|
62
|
+
* fill: 0xffffff
|
|
63
|
+
* }
|
|
64
|
+
* }));
|
|
65
|
+
*
|
|
66
|
+
* // 带样式的文本
|
|
67
|
+
* label.addComponent(new Text({
|
|
68
|
+
* text: '得分: 9999',
|
|
69
|
+
* style: {
|
|
70
|
+
* fontFamily: 'Arial',
|
|
71
|
+
* fontSize: 48,
|
|
72
|
+
* fontWeight: 'bold',
|
|
73
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
74
|
+
* stroke: '#000000',
|
|
75
|
+
* strokeThickness: 4,
|
|
76
|
+
* dropShadow: true,
|
|
77
|
+
* dropShadowDistance: 3
|
|
78
|
+
* }
|
|
79
|
+
* }));
|
|
80
|
+
* // 如需高清渲染,使用 Render 组件的 resolution 属性
|
|
81
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
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 = {};
|
|
47
|
-
this.resolution = 1;
|
|
48
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* 初始化组件
|
|
95
|
+
* @param obj - 初始化参数
|
|
96
|
+
* @param obj.text - 文本内容
|
|
97
|
+
* @param obj.style - 文本样式
|
|
98
|
+
*/
|
|
49
99
|
init(obj) {
|
|
50
100
|
const style = new pixi_js.TextStyle({
|
|
51
101
|
fontSize: 20,
|
|
@@ -61,27 +111,93 @@ class Text$2 extends eva_js.Component {
|
|
|
61
111
|
if (obj) {
|
|
62
112
|
this.text = obj.text;
|
|
63
113
|
Object.assign(this.style, obj.style);
|
|
64
|
-
if (obj.resolution !== undefined) {
|
|
65
|
-
this.resolution = obj.resolution;
|
|
66
|
-
}
|
|
67
114
|
}
|
|
68
115
|
}
|
|
69
116
|
}
|
|
117
|
+
/** 组件名称 */
|
|
70
118
|
Text$2.componentName = 'Text';
|
|
71
119
|
__decorate([
|
|
72
120
|
inspectorDecorator.type('string')
|
|
73
|
-
], Text$2.prototype, "text", void 0);
|
|
74
|
-
__decorate([
|
|
75
|
-
inspectorDecorator.type('number')
|
|
76
|
-
], Text$2.prototype, "resolution", void 0);
|
|
121
|
+
], Text$2.prototype, "text", void 0);
|
|
77
122
|
|
|
123
|
+
/**
|
|
124
|
+
* HTML 富文本组件
|
|
125
|
+
*
|
|
126
|
+
* HTMLText 组件支持渲染带有 HTML 标签的富文本内容。
|
|
127
|
+
* 可以在文本中使用 HTML 标签(如 `<b>`, `<i>`, `<span>` 等)来实现丰富的文本样式,
|
|
128
|
+
* 适用于聊天对话、新闻内容、富文本显示等需要多样式文本的场景。
|
|
129
|
+
*
|
|
130
|
+
* 支持的 HTML 标签:
|
|
131
|
+
* - `<b>` - 粗体
|
|
132
|
+
* - `<i>` - 斜体
|
|
133
|
+
* - `<span style="color:#ff0000">` - 自定义样式
|
|
134
|
+
* - `<br>` - 换行
|
|
135
|
+
* 以及更多标准 HTML 文本标签
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // 基础富文本
|
|
140
|
+
* const label = new GameObject('label');
|
|
141
|
+
* label.addComponent(new HTMLText({
|
|
142
|
+
* text: '这是<b>粗体</b>和<i>斜体</i>文本',
|
|
143
|
+
* style: {
|
|
144
|
+
* fontSize: 24,
|
|
145
|
+
* fill: '#000000',
|
|
146
|
+
* fontFamily: 'Arial'
|
|
147
|
+
* }
|
|
148
|
+
* }));
|
|
149
|
+
*
|
|
150
|
+
* // 带颜色的富文本
|
|
151
|
+
* label.addComponent(new HTMLText({
|
|
152
|
+
* text: '欢迎 <span style="color:#ff0000">玩家123</span> 加入游戏!',
|
|
153
|
+
* style: {
|
|
154
|
+
* fontSize: 20,
|
|
155
|
+
* wordWrap: true,
|
|
156
|
+
* wordWrapWidth: 300
|
|
157
|
+
* }
|
|
158
|
+
* }));
|
|
159
|
+
*
|
|
160
|
+
* // 自定义标签样式
|
|
161
|
+
* label.addComponent(new HTMLText({
|
|
162
|
+
* text: '获得 <gold>100</gold> 金币',
|
|
163
|
+
* style: {
|
|
164
|
+
* fontSize: 18,
|
|
165
|
+
* tagStyles: {
|
|
166
|
+
* gold: {
|
|
167
|
+
* fill: '#ffd700',
|
|
168
|
+
* fontWeight: 'bold'
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
* }));
|
|
173
|
+
*
|
|
174
|
+
* // 高分辨率渲染(推荐使用 Render 组件的 resolution 属性)
|
|
175
|
+
* label.addComponent(new HTMLText({
|
|
176
|
+
* text: '高清文本',
|
|
177
|
+
* textureStyle: {
|
|
178
|
+
* scaleMode: 'linear'
|
|
179
|
+
* }
|
|
180
|
+
* }));
|
|
181
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
78
184
|
class HTMLText extends eva_js.Component {
|
|
79
185
|
constructor() {
|
|
80
186
|
super(...arguments);
|
|
187
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
81
188
|
this.text = '';
|
|
189
|
+
/** 文本样式配置 */
|
|
82
190
|
this.style = {};
|
|
191
|
+
/** 纹理渲染配置 */
|
|
83
192
|
this.textureStyle = {};
|
|
84
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* 初始化组件
|
|
196
|
+
* @param obj - 初始化参数
|
|
197
|
+
* @param obj.text - 富文本内容
|
|
198
|
+
* @param obj.style - 文本样式
|
|
199
|
+
* @param obj.textureStyle - 纹理配置
|
|
200
|
+
*/
|
|
85
201
|
init(obj) {
|
|
86
202
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
87
203
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -90,6 +206,7 @@ class HTMLText extends eva_js.Component {
|
|
|
90
206
|
}
|
|
91
207
|
}
|
|
92
208
|
}
|
|
209
|
+
/** 组件名称 */
|
|
93
210
|
HTMLText.componentName = 'HTMLText';
|
|
94
211
|
__decorate([
|
|
95
212
|
inspectorDecorator.type('string')
|
|
@@ -127,6 +244,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
127
244
|
}
|
|
128
245
|
else {
|
|
129
246
|
this.change(changed);
|
|
247
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
130
248
|
const component = changed.component;
|
|
131
249
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
132
250
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -139,19 +257,18 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
139
257
|
addTextComponent(changed) {
|
|
140
258
|
return __awaiter(this, void 0, void 0, function* () {
|
|
141
259
|
const component = changed.component;
|
|
260
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
142
261
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
143
262
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
144
263
|
delete styleWithoutFont.fontFamily;
|
|
145
264
|
const initialText = fontFamily ? '' : component.text;
|
|
146
265
|
const text = new rendererAdapter.Text(initialText, styleWithoutFont);
|
|
147
|
-
if (component.resolution !== undefined && component.resolution > 0) {
|
|
148
|
-
text.resolution = component.resolution;
|
|
149
|
-
}
|
|
150
266
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
151
267
|
this.texts[changed.gameObject.id] = {
|
|
152
268
|
text,
|
|
153
269
|
component,
|
|
154
270
|
};
|
|
271
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
155
272
|
if (fontFamily) {
|
|
156
273
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
157
274
|
}
|
|
@@ -160,6 +277,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
160
277
|
addHTMLTextComponent(changed) {
|
|
161
278
|
return __awaiter(this, void 0, void 0, function* () {
|
|
162
279
|
const component = changed.component;
|
|
280
|
+
// 创建样式副本,先不设置 fontFamily
|
|
163
281
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
164
282
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
165
283
|
delete styleWithoutFont.fontFamily;
|
|
@@ -170,11 +288,15 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
170
288
|
text: htmlText,
|
|
171
289
|
component,
|
|
172
290
|
};
|
|
291
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
173
292
|
if (fontFamily) {
|
|
174
293
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
175
294
|
}
|
|
176
295
|
});
|
|
177
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* 等待字体资源加载完成并更新文本
|
|
299
|
+
*/
|
|
178
300
|
waitForFontResource(text, changed, fontFamily) {
|
|
179
301
|
return __awaiter(this, void 0, void 0, function* () {
|
|
180
302
|
if (!fontFamily) {
|
|
@@ -182,13 +304,17 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
182
304
|
}
|
|
183
305
|
try {
|
|
184
306
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
307
|
+
// 通过 resource 系统获取字体资源
|
|
185
308
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
186
309
|
yield eva_js.resource.getResource(fontName);
|
|
310
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
187
311
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
188
312
|
return;
|
|
313
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
189
314
|
const component = this.texts[changed.gameObject.id].component;
|
|
190
315
|
text.style.fontFamily = fontFamily;
|
|
191
316
|
text.text = component.text;
|
|
317
|
+
// 更新尺寸
|
|
192
318
|
}
|
|
193
319
|
catch (error) {
|
|
194
320
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -204,13 +330,8 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
204
330
|
else if (changed.prop.prop[0] === 'style') {
|
|
205
331
|
Object.assign(text.style, component.style);
|
|
206
332
|
}
|
|
207
|
-
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
208
|
-
const textComponent = component;
|
|
209
|
-
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
210
|
-
text.resolution = textComponent.resolution;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
333
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
334
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
214
335
|
const htmlComponent = component;
|
|
215
336
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
216
337
|
const index = container.getChildIndex(text);
|
|
@@ -238,7 +359,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
238
359
|
Text.systemName = 'Text';
|
|
239
360
|
Text = __decorate([
|
|
240
361
|
eva_js.decorators.componentObserver({
|
|
241
|
-
Text: ['text', { prop: ['style'], deep: true }
|
|
362
|
+
Text: ['text', { prop: ['style'], deep: true }],
|
|
242
363
|
HTMLText: ['text', { prop: ['style'], deep: true }, { prop: ['textureStyle'], deep: true }],
|
|
243
364
|
})
|
|
244
365
|
], Text);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("pixi.js"),t=require("@eva/eva.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("pixi.js"),t=require("@eva/eva.js"),n=require("@eva/inspector-decorator"),i=require("@eva/plugin-renderer"),s=require("@eva/renderer-adapter");
|
|
2
2
|
/*! *****************************************************************************
|
|
3
3
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
@@ -13,4 +13,4 @@ MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
|
13
13
|
See the Apache Version 2.0 License for specific language governing permissions
|
|
14
14
|
and limitations under the License.
|
|
15
15
|
***************************************************************************** */
|
|
16
|
-
function
|
|
16
|
+
function o(e,t,n,i){var s,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,n,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(r=(o<3?s(r):o>3?s(t,n,r):s(t,n))||r);return o>3&&r&&Object.defineProperty(t,n,r),r}function r(e,t,n,i){return new(n||(n=Promise))((function(s,o){function r(e){try{a(i.next(e))}catch(e){o(e)}}function c(e){try{a(i.throw(e))}catch(e){o(e)}}function a(e){e.done?s(e.value):new n((function(t){t(e.value)})).then(r,c)}a((i=i.apply(e,t||[])).next())}))}class c extends t.Component{constructor(){super(...arguments),this.text="",this.style={}}init(t){const n=new e.TextStyle({fontSize:20}),i={};for(const e in n)0===e.indexOf("_")&&(i[e.substring(1)]=n[e]);delete i.styleKey,this.style=i,t&&(this.text=t.text,Object.assign(this.style,t.style))}}c.componentName="Text",o([n.type("string")],c.prototype,"text",void 0);class a extends t.Component{constructor(){super(...arguments),this.text="",this.style={},this.textureStyle={}}init(e){this.style=Object.assign({fontSize:24,fill:"#000000",fontFamily:"Arial"},null==e?void 0:e.style),this.textureStyle=Object.assign({scaleMode:"linear",resolution:window.devicePixelRatio||1},null==e?void 0:e.textureStyle),e&&(this.text=e.text)}}a.componentName="HTMLText",o([n.type("string")],a.prototype,"text",void 0);let d=class extends i.Renderer{constructor(){super(...arguments),this.name="Text",this.texts={}}init(){this.renderSystem=this.game.getSystem(i.RendererSystem),this.renderSystem.rendererManager.register(this)}componentChanged(e){return r(this,void 0,void 0,(function*(){const n="Text"===e.componentName,i="HTMLText"===e.componentName;if(n||i)if(e.type===t.OBSERVER_TYPE.ADD)n?yield this.addTextComponent(e):yield this.addHTMLTextComponent(e),this.setSize(e);else if(e.type===t.OBSERVER_TYPE.REMOVE)this.containerManager.getContainer(e.gameObject.id).removeChild(this.texts[e.gameObject.id].text),this.texts[e.gameObject.id].text.destroy({children:!0}),delete this.texts[e.gameObject.id];else{this.change(e);const t=e.component;if("style"===e.prop.prop[0]&&t.style&&t.style.fontFamily){const{text:n}=this.texts[e.gameObject.id];yield this.waitForFontResource(n,e,t.style.fontFamily)}this.setSize(e)}}))}addTextComponent(e){return r(this,void 0,void 0,(function*(){const t=e.component,n=Object.assign({},t.style),i=n.fontFamily;delete n.fontFamily;const o=i?"":t.text,r=new s.Text(o,n);this.containerManager.getContainer(e.gameObject.id).addChildAt(r,0),this.texts[e.gameObject.id]={text:r,component:t},i&&(yield this.waitForFontResource(r,e,i))}))}addHTMLTextComponent(e){return r(this,void 0,void 0,(function*(){const t=e.component,n=Object.assign({},t.style),i=n.fontFamily;delete n.fontFamily;const o=i?"":t.text,r=new s.HTMLText(Object.assign({text:o,style:n},t.textureStyle&&{textureStyle:t.textureStyle}));this.containerManager.getContainer(e.gameObject.id).addChildAt(r,0),this.texts[e.gameObject.id]={text:r,component:t},i&&(yield this.waitForFontResource(r,e,i))}))}waitForFontResource(e,n,i){return r(this,void 0,void 0,(function*(){if(i)try{const s=Array.isArray(i)?i[0]:i,o=this.increaseAsyncId(n.gameObject.id);if(yield t.resource.getResource(s),!this.validateAsyncId(n.gameObject.id,o))return;const r=this.texts[n.gameObject.id].component;e.style.fontFamily=i,e.text=r.text}catch(e){console.warn(`字体资源 ${i} 加载失败:`,e)}}))}change(e){const{text:t,component:n}=this.texts[e.gameObject.id],i="HTMLText"===e.componentName;if("text"===e.prop.prop[0])t.text=n.text;else if("style"===e.prop.prop[0])Object.assign(t.style,n.style);else if("textureStyle"===e.prop.prop[0]&&i){const i=n,o=this.containerManager.getContainer(e.gameObject.id),r=o.getChildIndex(t);o.removeChild(t),t.destroy({children:!0});const c=new s.HTMLText({text:i.text,style:i.style,textureStyle:i.textureStyle});o.addChildAt(c,r),this.texts[e.gameObject.id].text=c}}setSize(e){const{transform:t}=e.gameObject;if(!t)return;const{text:n}=this.texts[e.gameObject.id],i=n.getSize();t.size.width=i.width,t.size.height=i.height}};d.systemName="Text",d=o([t.decorators.componentObserver({Text:["text",{prop:["style"],deep:!0}],HTMLText:["text",{prop:["style"],deep:!0},{prop:["textureStyle"],deep:!0}]})],d);var l=d;exports.HTMLText=a,exports.Text=c,exports.TextSystem=l;
|
|
@@ -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
|
+
* // 高分辨率渲染(推荐使用 Render 组件的 resolution 属性)
|
|
68
|
+
* label.addComponent(new HTMLText({
|
|
69
|
+
* text: '高清文本',
|
|
70
|
+
* textureStyle: {
|
|
71
|
+
* scaleMode: 'linear'
|
|
72
|
+
* }
|
|
73
|
+
* }));
|
|
74
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
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,61 @@ 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
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* // 基础文本
|
|
150
|
+
* const label = new GameObject('label');
|
|
151
|
+
* label.addComponent(new Text({
|
|
152
|
+
* text: 'Hello EVA!',
|
|
153
|
+
* style: {
|
|
154
|
+
* fontSize: 32,
|
|
155
|
+
* fill: 0xffffff
|
|
156
|
+
* }
|
|
157
|
+
* }));
|
|
158
|
+
*
|
|
159
|
+
* // 带样式的文本
|
|
160
|
+
* label.addComponent(new Text({
|
|
161
|
+
* text: '得分: 9999',
|
|
162
|
+
* style: {
|
|
163
|
+
* fontFamily: 'Arial',
|
|
164
|
+
* fontSize: 48,
|
|
165
|
+
* fontWeight: 'bold',
|
|
166
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
167
|
+
* stroke: '#000000',
|
|
168
|
+
* strokeThickness: 4,
|
|
169
|
+
* dropShadow: true,
|
|
170
|
+
* dropShadowDistance: 3
|
|
171
|
+
* }
|
|
172
|
+
* }));
|
|
173
|
+
* // 如需高清渲染,使用 Render 组件的 resolution 属性
|
|
174
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
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'];
|
|
67
|
-
|
|
184
|
+
/**
|
|
185
|
+
* 初始化组件
|
|
186
|
+
* @param obj - 初始化参数
|
|
187
|
+
* @param obj.text - 文本内容
|
|
188
|
+
* @param obj.style - 文本样式
|
|
189
|
+
*/
|
|
68
190
|
init(obj?: TextParams): void;
|
|
69
191
|
}
|
|
70
192
|
export { Text_2 as Text }
|
|
@@ -102,7 +224,6 @@ export declare interface TextParams {
|
|
|
102
224
|
wordWrapWidth?: number;
|
|
103
225
|
leading?: number;
|
|
104
226
|
};
|
|
105
|
-
resolution?: number;
|
|
106
227
|
}
|
|
107
228
|
|
|
108
229
|
export declare class TextSystem extends Renderer {
|
|
@@ -121,6 +242,9 @@ export declare class TextSystem extends Renderer {
|
|
|
121
242
|
componentChanged(changed: ComponentChanged): Promise<void>;
|
|
122
243
|
private addTextComponent;
|
|
123
244
|
private addHTMLTextComponent;
|
|
245
|
+
/**
|
|
246
|
+
* 等待字体资源加载完成并更新文本
|
|
247
|
+
*/
|
|
124
248
|
private waitForFontResource;
|
|
125
249
|
change(changed: ComponentChanged): void;
|
|
126
250
|
setSize(changed: ComponentChanged): void;
|
|
@@ -35,13 +35,63 @@ 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
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // 基础文本
|
|
53
|
+
* const label = new GameObject('label');
|
|
54
|
+
* label.addComponent(new Text({
|
|
55
|
+
* text: 'Hello EVA!',
|
|
56
|
+
* style: {
|
|
57
|
+
* fontSize: 32,
|
|
58
|
+
* fill: 0xffffff
|
|
59
|
+
* }
|
|
60
|
+
* }));
|
|
61
|
+
*
|
|
62
|
+
* // 带样式的文本
|
|
63
|
+
* label.addComponent(new Text({
|
|
64
|
+
* text: '得分: 9999',
|
|
65
|
+
* style: {
|
|
66
|
+
* fontFamily: 'Arial',
|
|
67
|
+
* fontSize: 48,
|
|
68
|
+
* fontWeight: 'bold',
|
|
69
|
+
* fill: ['#ff0000', '#ffff00'], // 渐变色
|
|
70
|
+
* stroke: '#000000',
|
|
71
|
+
* strokeThickness: 4,
|
|
72
|
+
* dropShadow: true,
|
|
73
|
+
* dropShadowDistance: 3
|
|
74
|
+
* }
|
|
75
|
+
* }));
|
|
76
|
+
* // 如需高清渲染,使用 Render 组件的 resolution 属性
|
|
77
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
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 = {};
|
|
43
|
-
this.resolution = 1;
|
|
44
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* 初始化组件
|
|
91
|
+
* @param obj - 初始化参数
|
|
92
|
+
* @param obj.text - 文本内容
|
|
93
|
+
* @param obj.style - 文本样式
|
|
94
|
+
*/
|
|
45
95
|
init(obj) {
|
|
46
96
|
const style = new TextStyle({
|
|
47
97
|
fontSize: 20,
|
|
@@ -57,27 +107,93 @@ class Text$2 extends Component {
|
|
|
57
107
|
if (obj) {
|
|
58
108
|
this.text = obj.text;
|
|
59
109
|
Object.assign(this.style, obj.style);
|
|
60
|
-
if (obj.resolution !== undefined) {
|
|
61
|
-
this.resolution = obj.resolution;
|
|
62
|
-
}
|
|
63
110
|
}
|
|
64
111
|
}
|
|
65
112
|
}
|
|
113
|
+
/** 组件名称 */
|
|
66
114
|
Text$2.componentName = 'Text';
|
|
67
115
|
__decorate([
|
|
68
116
|
type('string')
|
|
69
|
-
], Text$2.prototype, "text", void 0);
|
|
70
|
-
__decorate([
|
|
71
|
-
type('number')
|
|
72
|
-
], Text$2.prototype, "resolution", void 0);
|
|
117
|
+
], Text$2.prototype, "text", void 0);
|
|
73
118
|
|
|
119
|
+
/**
|
|
120
|
+
* HTML 富文本组件
|
|
121
|
+
*
|
|
122
|
+
* HTMLText 组件支持渲染带有 HTML 标签的富文本内容。
|
|
123
|
+
* 可以在文本中使用 HTML 标签(如 `<b>`, `<i>`, `<span>` 等)来实现丰富的文本样式,
|
|
124
|
+
* 适用于聊天对话、新闻内容、富文本显示等需要多样式文本的场景。
|
|
125
|
+
*
|
|
126
|
+
* 支持的 HTML 标签:
|
|
127
|
+
* - `<b>` - 粗体
|
|
128
|
+
* - `<i>` - 斜体
|
|
129
|
+
* - `<span style="color:#ff0000">` - 自定义样式
|
|
130
|
+
* - `<br>` - 换行
|
|
131
|
+
* 以及更多标准 HTML 文本标签
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* // 基础富文本
|
|
136
|
+
* const label = new GameObject('label');
|
|
137
|
+
* label.addComponent(new HTMLText({
|
|
138
|
+
* text: '这是<b>粗体</b>和<i>斜体</i>文本',
|
|
139
|
+
* style: {
|
|
140
|
+
* fontSize: 24,
|
|
141
|
+
* fill: '#000000',
|
|
142
|
+
* fontFamily: 'Arial'
|
|
143
|
+
* }
|
|
144
|
+
* }));
|
|
145
|
+
*
|
|
146
|
+
* // 带颜色的富文本
|
|
147
|
+
* label.addComponent(new HTMLText({
|
|
148
|
+
* text: '欢迎 <span style="color:#ff0000">玩家123</span> 加入游戏!',
|
|
149
|
+
* style: {
|
|
150
|
+
* fontSize: 20,
|
|
151
|
+
* wordWrap: true,
|
|
152
|
+
* wordWrapWidth: 300
|
|
153
|
+
* }
|
|
154
|
+
* }));
|
|
155
|
+
*
|
|
156
|
+
* // 自定义标签样式
|
|
157
|
+
* label.addComponent(new HTMLText({
|
|
158
|
+
* text: '获得 <gold>100</gold> 金币',
|
|
159
|
+
* style: {
|
|
160
|
+
* fontSize: 18,
|
|
161
|
+
* tagStyles: {
|
|
162
|
+
* gold: {
|
|
163
|
+
* fill: '#ffd700',
|
|
164
|
+
* fontWeight: 'bold'
|
|
165
|
+
* }
|
|
166
|
+
* }
|
|
167
|
+
* }
|
|
168
|
+
* }));
|
|
169
|
+
*
|
|
170
|
+
* // 高分辨率渲染(推荐使用 Render 组件的 resolution 属性)
|
|
171
|
+
* label.addComponent(new HTMLText({
|
|
172
|
+
* text: '高清文本',
|
|
173
|
+
* textureStyle: {
|
|
174
|
+
* scaleMode: 'linear'
|
|
175
|
+
* }
|
|
176
|
+
* }));
|
|
177
|
+
* label.addComponent(new Render({ resolution: 2 }));
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
74
180
|
class HTMLText extends Component {
|
|
75
181
|
constructor() {
|
|
76
182
|
super(...arguments);
|
|
183
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
77
184
|
this.text = '';
|
|
185
|
+
/** 文本样式配置 */
|
|
78
186
|
this.style = {};
|
|
187
|
+
/** 纹理渲染配置 */
|
|
79
188
|
this.textureStyle = {};
|
|
80
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* 初始化组件
|
|
192
|
+
* @param obj - 初始化参数
|
|
193
|
+
* @param obj.text - 富文本内容
|
|
194
|
+
* @param obj.style - 文本样式
|
|
195
|
+
* @param obj.textureStyle - 纹理配置
|
|
196
|
+
*/
|
|
81
197
|
init(obj) {
|
|
82
198
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
83
199
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -86,6 +202,7 @@ class HTMLText extends Component {
|
|
|
86
202
|
}
|
|
87
203
|
}
|
|
88
204
|
}
|
|
205
|
+
/** 组件名称 */
|
|
89
206
|
HTMLText.componentName = 'HTMLText';
|
|
90
207
|
__decorate([
|
|
91
208
|
type('string')
|
|
@@ -123,6 +240,7 @@ let Text = class Text extends Renderer {
|
|
|
123
240
|
}
|
|
124
241
|
else {
|
|
125
242
|
this.change(changed);
|
|
243
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
126
244
|
const component = changed.component;
|
|
127
245
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
128
246
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -135,19 +253,18 @@ let Text = class Text extends Renderer {
|
|
|
135
253
|
addTextComponent(changed) {
|
|
136
254
|
return __awaiter(this, void 0, void 0, function* () {
|
|
137
255
|
const component = changed.component;
|
|
256
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
138
257
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
139
258
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
140
259
|
delete styleWithoutFont.fontFamily;
|
|
141
260
|
const initialText = fontFamily ? '' : component.text;
|
|
142
261
|
const text = new Text$3(initialText, styleWithoutFont);
|
|
143
|
-
if (component.resolution !== undefined && component.resolution > 0) {
|
|
144
|
-
text.resolution = component.resolution;
|
|
145
|
-
}
|
|
146
262
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
147
263
|
this.texts[changed.gameObject.id] = {
|
|
148
264
|
text,
|
|
149
265
|
component,
|
|
150
266
|
};
|
|
267
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
151
268
|
if (fontFamily) {
|
|
152
269
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
153
270
|
}
|
|
@@ -156,6 +273,7 @@ let Text = class Text extends Renderer {
|
|
|
156
273
|
addHTMLTextComponent(changed) {
|
|
157
274
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
275
|
const component = changed.component;
|
|
276
|
+
// 创建样式副本,先不设置 fontFamily
|
|
159
277
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
160
278
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
161
279
|
delete styleWithoutFont.fontFamily;
|
|
@@ -166,11 +284,15 @@ let Text = class Text extends Renderer {
|
|
|
166
284
|
text: htmlText,
|
|
167
285
|
component,
|
|
168
286
|
};
|
|
287
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
169
288
|
if (fontFamily) {
|
|
170
289
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
171
290
|
}
|
|
172
291
|
});
|
|
173
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* 等待字体资源加载完成并更新文本
|
|
295
|
+
*/
|
|
174
296
|
waitForFontResource(text, changed, fontFamily) {
|
|
175
297
|
return __awaiter(this, void 0, void 0, function* () {
|
|
176
298
|
if (!fontFamily) {
|
|
@@ -178,13 +300,17 @@ let Text = class Text extends Renderer {
|
|
|
178
300
|
}
|
|
179
301
|
try {
|
|
180
302
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
303
|
+
// 通过 resource 系统获取字体资源
|
|
181
304
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
182
305
|
yield resource.getResource(fontName);
|
|
306
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
183
307
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
184
308
|
return;
|
|
309
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
185
310
|
const component = this.texts[changed.gameObject.id].component;
|
|
186
311
|
text.style.fontFamily = fontFamily;
|
|
187
312
|
text.text = component.text;
|
|
313
|
+
// 更新尺寸
|
|
188
314
|
}
|
|
189
315
|
catch (error) {
|
|
190
316
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -200,13 +326,8 @@ let Text = class Text extends Renderer {
|
|
|
200
326
|
else if (changed.prop.prop[0] === 'style') {
|
|
201
327
|
Object.assign(text.style, component.style);
|
|
202
328
|
}
|
|
203
|
-
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
204
|
-
const textComponent = component;
|
|
205
|
-
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
206
|
-
text.resolution = textComponent.resolution;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
329
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
330
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
210
331
|
const htmlComponent = component;
|
|
211
332
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
212
333
|
const index = container.getChildIndex(text);
|
|
@@ -234,7 +355,7 @@ let Text = class Text extends Renderer {
|
|
|
234
355
|
Text.systemName = 'Text';
|
|
235
356
|
Text = __decorate([
|
|
236
357
|
decorators.componentObserver({
|
|
237
|
-
Text: ['text', { prop: ['style'], deep: true }
|
|
358
|
+
Text: ['text', { prop: ['style'], deep: true }],
|
|
238
359
|
HTMLText: ['text', { prop: ['style'], deep: true }, { prop: ['textureStyle'], deep: true }],
|
|
239
360
|
})
|
|
240
361
|
], 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.29",
|
|
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.29",
|
|
23
|
+
"@eva/renderer-adapter": "2.0.1-beta.29",
|
|
24
|
+
"@eva/eva.js": "2.0.1-beta.29",
|
|
25
25
|
"pixi.js": "^8.8.1"
|
|
26
26
|
}
|
|
27
27
|
}
|