@eva/plugin-renderer-text 2.0.1-beta.26 → 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.
- package/dist/EVA.plugin.renderer.text.js +14 -1
- package/dist/EVA.plugin.renderer.text.min.js +1 -1
- package/dist/plugin-renderer-text.cjs.js +159 -2
- package/dist/plugin-renderer-text.cjs.prod.js +2 -2
- package/dist/plugin-renderer-text.d.ts +130 -0
- package/dist/plugin-renderer-text.esm.js +159 -2
- package/package.json +4 -4
|
@@ -60,6 +60,7 @@ 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;
|
|
63
64
|
}
|
|
64
65
|
init(obj) {
|
|
65
66
|
const style = new pixi_js.TextStyle({
|
|
@@ -76,11 +77,15 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
76
77
|
if (obj) {
|
|
77
78
|
this.text = obj.text;
|
|
78
79
|
_extends(this.style, obj.style);
|
|
80
|
+
if (obj.resolution !== undefined) {
|
|
81
|
+
this.resolution = obj.resolution;
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
Text$2.componentName = 'Text';
|
|
83
87
|
__decorate([type('string')], Text$2.prototype, "text", void 0);
|
|
88
|
+
__decorate([type('number')], Text$2.prototype, "resolution", void 0);
|
|
84
89
|
class HTMLText extends eva_js.Component {
|
|
85
90
|
constructor() {
|
|
86
91
|
super(...arguments);
|
|
@@ -154,6 +159,9 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
154
159
|
delete styleWithoutFont.fontFamily;
|
|
155
160
|
const initialText = fontFamily ? '' : component.text;
|
|
156
161
|
const text = new rendererAdapter.Text(initialText, styleWithoutFont);
|
|
162
|
+
if (component.resolution !== undefined && component.resolution > 0) {
|
|
163
|
+
text.resolution = component.resolution;
|
|
164
|
+
}
|
|
157
165
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
158
166
|
this.texts[changed.gameObject.id] = {
|
|
159
167
|
text,
|
|
@@ -215,6 +223,11 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
215
223
|
text.text = component.text;
|
|
216
224
|
} else if (changed.prop.prop[0] === 'style') {
|
|
217
225
|
_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
|
+
}
|
|
218
231
|
} else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
219
232
|
const htmlComponent = component;
|
|
220
233
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
@@ -250,7 +263,7 @@ var _EVA_IIFE_text = function (exports, pixi_js, eva_js, pluginRenderer, rendere
|
|
|
250
263
|
Text: ['text', {
|
|
251
264
|
prop: ['style'],
|
|
252
265
|
deep: true
|
|
253
|
-
}],
|
|
266
|
+
}, 'resolution'],
|
|
254
267
|
HTMLText: ['text', {
|
|
255
268
|
prop: ['style'],
|
|
256
269
|
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 o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}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,o,i){"use strict";function s(t,e,n,o){var i,s=arguments.length,r=s<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,n):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(t,e,n,o);else for(var l=t.length-1;l>=0;l--)(i=t[l])&&(r=(s<3?i(r):s>3?i(e,n,r):i(e,n))||r);return s>3&&r&&Object.defineProperty(e,n,r),r}function r(t,e,n,o){return new(n||(n=Promise))((function(i,s){function r(t){try{c(o.next(t))}catch(t){s(t)}}function l(t){try{c(o.throw(t))}catch(t){s(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(r,l)}c((o=o.apply(t,e||[])).next())}))}function l(t){return function(e,n){var o=function(t,e){return t.constructor.IDEProps||(t.constructor.IDEProps={}),t.constructor.IDEProps[e]||(t.constructor.IDEProps[e]={}),t.constructor.IDEProps[e]}(e,n);o.key=n,o.type=t}}class c extends n.Component{constructor(){super(...arguments),this.text="",this.style={},this.resolution=1}init(t){const n=new e.TextStyle({fontSize:20}),o={};for(const t in n)0===t.indexOf("_")&&(o[t.substring(1)]=n[t]);delete o.styleKey,this.style=o,t&&(this.text=t.text,_extends(this.style,t.style),void 0!==t.resolution&&(this.resolution=t.resolution))}}c.componentName="Text",s([l("string")],c.prototype,"text",void 0),s([l("number")],c.prototype,"resolution",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([l("string")],a.prototype,"text",void 0);let d=class extends o.Renderer{constructor(){super(...arguments),this.name="Text",this.texts={}}init(){this.renderSystem=this.game.getSystem(o.RendererSystem),this.renderSystem.rendererManager.register(this)}componentChanged(t){return r(this,void 0,void 0,(function*(){const e="Text"===t.componentName,o="HTMLText"===t.componentName;if(e||o)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),o=n.fontFamily;delete n.fontFamily;const s=o?"":e.text,r=new i.Text(s,n);void 0!==e.resolution&&e.resolution>0&&(r.resolution=e.resolution),this.containerManager.getContainer(t.gameObject.id).addChildAt(r,0),this.texts[t.gameObject.id]={text:r,component:e},o&&(yield this.waitForFontResource(r,t,o))}))}addHTMLTextComponent(t){return r(this,void 0,void 0,(function*(){const e=t.component,n=_extends({},e.style),o=n.fontFamily;delete n.fontFamily;const s=o?"":e.text,r=new i.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},o&&(yield this.waitForFontResource(r,t,o))}))}waitForFontResource(t,e,o){return r(this,void 0,void 0,(function*(){if(o)try{const i=Array.isArray(o)?o[0]:o,s=this.increaseAsyncId(e.gameObject.id);if(yield n.resource.getResource(i),!this.validateAsyncId(e.gameObject.id,s))return;const r=this.texts[e.gameObject.id].component;t.style.fontFamily=o,t.text=r.text}catch(t){console.warn(`字体资源 ${o} 加载失败:`,t)}}))}change(t){const{text:e,component:n}=this.texts[t.gameObject.id],o="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("resolution"!==t.prop.prop[0]||o){if("textureStyle"===t.prop.prop[0]&&o){const o=n,s=this.containerManager.getContainer(t.gameObject.id),r=s.getChildIndex(e);s.removeChild(e),e.destroy({children:!0});const l=new i.HTMLText({text:o.text,style:o.style,textureStyle:o.textureStyle});s.addChildAt(l,r),this.texts[t.gameObject.id].text=l}}else{const t=n;void 0!==t.resolution&&t.resolution>0&&(e.resolution=t.resolution)}}setSize(t){const{transform:e}=t.gameObject;if(!e)return;const{text:n}=this.texts[t.gameObject.id],o=n.getSize();e.size.width=o.width,e.size.height=o.height}};d.systemName="Text",d=s([n.decorators.componentObserver({Text:["text",{prop:["style"],deep:!0},"resolution"],HTMLText:["text",{prop:["style"],deep:!0},{prop:["textureStyle"],deep:!0}]})],d);var u=d;return t.HTMLText=a,t.Text=c,t.TextSystem=u,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,12 +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
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
93
|
+
this.resolution = 1;
|
|
47
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* 初始化组件
|
|
97
|
+
* @param obj - 初始化参数
|
|
98
|
+
* @param obj.text - 文本内容
|
|
99
|
+
* @param obj.style - 文本样式
|
|
100
|
+
* @param obj.resolution - 渲染分辨率
|
|
101
|
+
*/
|
|
48
102
|
init(obj) {
|
|
49
103
|
const style = new pixi_js.TextStyle({
|
|
50
104
|
fontSize: 20,
|
|
@@ -60,21 +114,99 @@ class Text$2 extends eva_js.Component {
|
|
|
60
114
|
if (obj) {
|
|
61
115
|
this.text = obj.text;
|
|
62
116
|
Object.assign(this.style, obj.style);
|
|
117
|
+
if (obj.resolution !== undefined) {
|
|
118
|
+
this.resolution = obj.resolution;
|
|
119
|
+
}
|
|
63
120
|
}
|
|
64
121
|
}
|
|
65
122
|
}
|
|
123
|
+
/** 组件名称 */
|
|
66
124
|
Text$2.componentName = 'Text';
|
|
67
125
|
__decorate([
|
|
68
126
|
inspectorDecorator.type('string')
|
|
69
|
-
], Text$2.prototype, "text", void 0);
|
|
127
|
+
], Text$2.prototype, "text", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
inspectorDecorator.type('number')
|
|
130
|
+
], Text$2.prototype, "resolution", void 0);
|
|
70
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
|
+
*/
|
|
71
193
|
class HTMLText extends eva_js.Component {
|
|
72
194
|
constructor() {
|
|
73
195
|
super(...arguments);
|
|
196
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
74
197
|
this.text = '';
|
|
198
|
+
/** 文本样式配置 */
|
|
75
199
|
this.style = {};
|
|
200
|
+
/** 纹理渲染配置 */
|
|
76
201
|
this.textureStyle = {};
|
|
77
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* 初始化组件
|
|
205
|
+
* @param obj - 初始化参数
|
|
206
|
+
* @param obj.text - 富文本内容
|
|
207
|
+
* @param obj.style - 文本样式
|
|
208
|
+
* @param obj.textureStyle - 纹理配置
|
|
209
|
+
*/
|
|
78
210
|
init(obj) {
|
|
79
211
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
80
212
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -83,6 +215,7 @@ class HTMLText extends eva_js.Component {
|
|
|
83
215
|
}
|
|
84
216
|
}
|
|
85
217
|
}
|
|
218
|
+
/** 组件名称 */
|
|
86
219
|
HTMLText.componentName = 'HTMLText';
|
|
87
220
|
__decorate([
|
|
88
221
|
inspectorDecorator.type('string')
|
|
@@ -120,6 +253,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
120
253
|
}
|
|
121
254
|
else {
|
|
122
255
|
this.change(changed);
|
|
256
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
123
257
|
const component = changed.component;
|
|
124
258
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
125
259
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -132,16 +266,22 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
132
266
|
addTextComponent(changed) {
|
|
133
267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
134
268
|
const component = changed.component;
|
|
269
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
135
270
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
136
271
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
137
272
|
delete styleWithoutFont.fontFamily;
|
|
138
273
|
const initialText = fontFamily ? '' : component.text;
|
|
139
274
|
const text = new rendererAdapter.Text(initialText, styleWithoutFont);
|
|
275
|
+
// 设置 resolution 以提升清晰度
|
|
276
|
+
if (component.resolution !== undefined && component.resolution > 0) {
|
|
277
|
+
text.resolution = component.resolution;
|
|
278
|
+
}
|
|
140
279
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
141
280
|
this.texts[changed.gameObject.id] = {
|
|
142
281
|
text,
|
|
143
282
|
component,
|
|
144
283
|
};
|
|
284
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
145
285
|
if (fontFamily) {
|
|
146
286
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
147
287
|
}
|
|
@@ -150,6 +290,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
150
290
|
addHTMLTextComponent(changed) {
|
|
151
291
|
return __awaiter(this, void 0, void 0, function* () {
|
|
152
292
|
const component = changed.component;
|
|
293
|
+
// 创建样式副本,先不设置 fontFamily
|
|
153
294
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
154
295
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
155
296
|
delete styleWithoutFont.fontFamily;
|
|
@@ -160,11 +301,15 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
160
301
|
text: htmlText,
|
|
161
302
|
component,
|
|
162
303
|
};
|
|
304
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
163
305
|
if (fontFamily) {
|
|
164
306
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
165
307
|
}
|
|
166
308
|
});
|
|
167
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* 等待字体资源加载完成并更新文本
|
|
312
|
+
*/
|
|
168
313
|
waitForFontResource(text, changed, fontFamily) {
|
|
169
314
|
return __awaiter(this, void 0, void 0, function* () {
|
|
170
315
|
if (!fontFamily) {
|
|
@@ -172,13 +317,17 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
172
317
|
}
|
|
173
318
|
try {
|
|
174
319
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
320
|
+
// 通过 resource 系统获取字体资源
|
|
175
321
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
176
322
|
yield eva_js.resource.getResource(fontName);
|
|
323
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
177
324
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
178
325
|
return;
|
|
326
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
179
327
|
const component = this.texts[changed.gameObject.id].component;
|
|
180
328
|
text.style.fontFamily = fontFamily;
|
|
181
329
|
text.text = component.text;
|
|
330
|
+
// 更新尺寸
|
|
182
331
|
}
|
|
183
332
|
catch (error) {
|
|
184
333
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -194,7 +343,15 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
194
343
|
else if (changed.prop.prop[0] === 'style') {
|
|
195
344
|
Object.assign(text.style, component.style);
|
|
196
345
|
}
|
|
346
|
+
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
347
|
+
// 更新 resolution
|
|
348
|
+
const textComponent = component;
|
|
349
|
+
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
350
|
+
text.resolution = textComponent.resolution;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
197
353
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
354
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
198
355
|
const htmlComponent = component;
|
|
199
356
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
200
357
|
const index = container.getChildIndex(text);
|
|
@@ -222,7 +379,7 @@ let Text = class Text extends pluginRenderer.Renderer {
|
|
|
222
379
|
Text.systemName = 'Text';
|
|
223
380
|
Text = __decorate([
|
|
224
381
|
eva_js.decorators.componentObserver({
|
|
225
|
-
Text: ['text', { prop: ['style'], deep: true }],
|
|
382
|
+
Text: ['text', { prop: ['style'], deep: true }, 'resolution'],
|
|
226
383
|
HTMLText: ['text', { prop: ['style'], deep: true }, { prop: ['textureStyle'], deep: true }],
|
|
227
384
|
})
|
|
228
385
|
], 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"),i=require("@eva/inspector-decorator"),o=require("@eva/plugin-renderer"),n=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 s(e,t,i,o){var n,s=arguments.length,r=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,i,o);else for(var c=e.length-1;c>=0;c--)(n=e[c])&&(r=(s<3?n(r):s>3?n(t,i,r):n(t,i))||r);return s>3&&r&&Object.defineProperty(t,i,r),r}function r(e,t,i,o){return new(i||(i=Promise))((function(n,s){function r(e){try{l(o.next(e))}catch(e){s(e)}}function c(e){try{l(o.throw(e))}catch(e){s(e)}}function l(e){e.done?n(e.value):new i((function(t){t(e.value)})).then(r,c)}l((o=o.apply(e,t||[])).next())}))}class c extends t.Component{constructor(){super(...arguments),this.text="",this.style={},this.resolution=1}init(t){const i=new e.TextStyle({fontSize:20}),o={};for(const e in i)0===e.indexOf("_")&&(o[e.substring(1)]=i[e]);delete o.styleKey,this.style=o,t&&(this.text=t.text,Object.assign(this.style,t.style),void 0!==t.resolution&&(this.resolution=t.resolution))}}c.componentName="Text",s([i.type("string")],c.prototype,"text",void 0),s([i.type("number")],c.prototype,"resolution",void 0);class l 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)}}l.componentName="HTMLText",s([i.type("string")],l.prototype,"text",void 0);let a=class extends o.Renderer{constructor(){super(...arguments),this.name="Text",this.texts={}}init(){this.renderSystem=this.game.getSystem(o.RendererSystem),this.renderSystem.rendererManager.register(this)}componentChanged(e){return r(this,void 0,void 0,(function*(){const i="Text"===e.componentName,o="HTMLText"===e.componentName;if(i||o)if(e.type===t.OBSERVER_TYPE.ADD)i?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:i}=this.texts[e.gameObject.id];yield this.waitForFontResource(i,e,t.style.fontFamily)}this.setSize(e)}}))}addTextComponent(e){return r(this,void 0,void 0,(function*(){const t=e.component,i=Object.assign({},t.style),o=i.fontFamily;delete i.fontFamily;const s=o?"":t.text,r=new n.Text(s,i);void 0!==t.resolution&&t.resolution>0&&(r.resolution=t.resolution),this.containerManager.getContainer(e.gameObject.id).addChildAt(r,0),this.texts[e.gameObject.id]={text:r,component:t},o&&(yield this.waitForFontResource(r,e,o))}))}addHTMLTextComponent(e){return r(this,void 0,void 0,(function*(){const t=e.component,i=Object.assign({},t.style),o=i.fontFamily;delete i.fontFamily;const s=o?"":t.text,r=new n.HTMLText(Object.assign({text:s,style:i},t.textureStyle&&{textureStyle:t.textureStyle}));this.containerManager.getContainer(e.gameObject.id).addChildAt(r,0),this.texts[e.gameObject.id]={text:r,component:t},o&&(yield this.waitForFontResource(r,e,o))}))}waitForFontResource(e,i,o){return r(this,void 0,void 0,(function*(){if(o)try{const n=Array.isArray(o)?o[0]:o,s=this.increaseAsyncId(i.gameObject.id);if(yield t.resource.getResource(n),!this.validateAsyncId(i.gameObject.id,s))return;const r=this.texts[i.gameObject.id].component;e.style.fontFamily=o,e.text=r.text}catch(e){console.warn(`字体资源 ${o} 加载失败:`,e)}}))}change(e){const{text:t,component:i}=this.texts[e.gameObject.id],o="HTMLText"===e.componentName;if("text"===e.prop.prop[0])t.text=i.text;else if("style"===e.prop.prop[0])Object.assign(t.style,i.style);else if("resolution"!==e.prop.prop[0]||o){if("textureStyle"===e.prop.prop[0]&&o){const o=i,s=this.containerManager.getContainer(e.gameObject.id),r=s.getChildIndex(t);s.removeChild(t),t.destroy({children:!0});const c=new n.HTMLText({text:o.text,style:o.style,textureStyle:o.textureStyle});s.addChildAt(c,r),this.texts[e.gameObject.id].text=c}}else{const e=i;void 0!==e.resolution&&e.resolution>0&&(t.resolution=e.resolution)}}setSize(e){const{transform:t}=e.gameObject;if(!t)return;const{text:i}=this.texts[e.gameObject.id],o=i.getSize();t.size.width=o.width,t.size.height=o.height}};a.systemName="Text",a=s([t.decorators.componentObserver({Text:["text",{prop:["style"],deep:!0},"resolution"],HTMLText:["text",{prop:["style"],deep:!0},{prop:["textureStyle"],deep:!0}]})],a);var d=a;exports.HTMLText=l,exports.Text=c,exports.TextSystem=d;
|
|
@@ -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,10 +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
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
185
|
+
resolution: number;
|
|
186
|
+
/**
|
|
187
|
+
* 初始化组件
|
|
188
|
+
* @param obj - 初始化参数
|
|
189
|
+
* @param obj.text - 文本内容
|
|
190
|
+
* @param obj.style - 文本样式
|
|
191
|
+
* @param obj.resolution - 渲染分辨率
|
|
192
|
+
*/
|
|
67
193
|
init(obj?: TextParams): void;
|
|
68
194
|
}
|
|
69
195
|
export { Text_2 as Text }
|
|
@@ -101,6 +227,7 @@ export declare interface TextParams {
|
|
|
101
227
|
wordWrapWidth?: number;
|
|
102
228
|
leading?: number;
|
|
103
229
|
};
|
|
230
|
+
resolution?: number;
|
|
104
231
|
}
|
|
105
232
|
|
|
106
233
|
export declare class TextSystem extends Renderer {
|
|
@@ -119,6 +246,9 @@ export declare class TextSystem extends Renderer {
|
|
|
119
246
|
componentChanged(changed: ComponentChanged): Promise<void>;
|
|
120
247
|
private addTextComponent;
|
|
121
248
|
private addHTMLTextComponent;
|
|
249
|
+
/**
|
|
250
|
+
* 等待字体资源加载完成并更新文本
|
|
251
|
+
*/
|
|
122
252
|
private waitForFontResource;
|
|
123
253
|
change(changed: ComponentChanged): void;
|
|
124
254
|
setSize(changed: ComponentChanged): void;
|
|
@@ -35,12 +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
|
+
/** 渲染分辨率,值越大文本越清晰但性能消耗越大 */
|
|
89
|
+
this.resolution = 1;
|
|
43
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* 初始化组件
|
|
93
|
+
* @param obj - 初始化参数
|
|
94
|
+
* @param obj.text - 文本内容
|
|
95
|
+
* @param obj.style - 文本样式
|
|
96
|
+
* @param obj.resolution - 渲染分辨率
|
|
97
|
+
*/
|
|
44
98
|
init(obj) {
|
|
45
99
|
const style = new TextStyle({
|
|
46
100
|
fontSize: 20,
|
|
@@ -56,21 +110,99 @@ class Text$2 extends Component {
|
|
|
56
110
|
if (obj) {
|
|
57
111
|
this.text = obj.text;
|
|
58
112
|
Object.assign(this.style, obj.style);
|
|
113
|
+
if (obj.resolution !== undefined) {
|
|
114
|
+
this.resolution = obj.resolution;
|
|
115
|
+
}
|
|
59
116
|
}
|
|
60
117
|
}
|
|
61
118
|
}
|
|
119
|
+
/** 组件名称 */
|
|
62
120
|
Text$2.componentName = 'Text';
|
|
63
121
|
__decorate([
|
|
64
122
|
type('string')
|
|
65
|
-
], Text$2.prototype, "text", void 0);
|
|
123
|
+
], Text$2.prototype, "text", void 0);
|
|
124
|
+
__decorate([
|
|
125
|
+
type('number')
|
|
126
|
+
], Text$2.prototype, "resolution", void 0);
|
|
66
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
|
+
*/
|
|
67
189
|
class HTMLText extends Component {
|
|
68
190
|
constructor() {
|
|
69
191
|
super(...arguments);
|
|
192
|
+
/** 富文本内容(支持 HTML 标签) */
|
|
70
193
|
this.text = '';
|
|
194
|
+
/** 文本样式配置 */
|
|
71
195
|
this.style = {};
|
|
196
|
+
/** 纹理渲染配置 */
|
|
72
197
|
this.textureStyle = {};
|
|
73
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* 初始化组件
|
|
201
|
+
* @param obj - 初始化参数
|
|
202
|
+
* @param obj.text - 富文本内容
|
|
203
|
+
* @param obj.style - 文本样式
|
|
204
|
+
* @param obj.textureStyle - 纹理配置
|
|
205
|
+
*/
|
|
74
206
|
init(obj) {
|
|
75
207
|
this.style = Object.assign({ fontSize: 24, fill: '#000000', fontFamily: 'Arial' }, obj === null || obj === void 0 ? void 0 : obj.style);
|
|
76
208
|
this.textureStyle = Object.assign({ scaleMode: 'linear', resolution: window.devicePixelRatio || 1 }, obj === null || obj === void 0 ? void 0 : obj.textureStyle);
|
|
@@ -79,6 +211,7 @@ class HTMLText extends Component {
|
|
|
79
211
|
}
|
|
80
212
|
}
|
|
81
213
|
}
|
|
214
|
+
/** 组件名称 */
|
|
82
215
|
HTMLText.componentName = 'HTMLText';
|
|
83
216
|
__decorate([
|
|
84
217
|
type('string')
|
|
@@ -116,6 +249,7 @@ let Text = class Text extends Renderer {
|
|
|
116
249
|
}
|
|
117
250
|
else {
|
|
118
251
|
this.change(changed);
|
|
252
|
+
// 如果样式改变且涉及字体,也需要等待字体资源加载
|
|
119
253
|
const component = changed.component;
|
|
120
254
|
if (changed.prop.prop[0] === 'style' && component.style && component.style.fontFamily) {
|
|
121
255
|
const { text } = this.texts[changed.gameObject.id];
|
|
@@ -128,16 +262,22 @@ let Text = class Text extends Renderer {
|
|
|
128
262
|
addTextComponent(changed) {
|
|
129
263
|
return __awaiter(this, void 0, void 0, function* () {
|
|
130
264
|
const component = changed.component;
|
|
265
|
+
// 创建文本样式副本,先不设置 fontFamily
|
|
131
266
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
132
267
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
133
268
|
delete styleWithoutFont.fontFamily;
|
|
134
269
|
const initialText = fontFamily ? '' : component.text;
|
|
135
270
|
const text = new Text$3(initialText, styleWithoutFont);
|
|
271
|
+
// 设置 resolution 以提升清晰度
|
|
272
|
+
if (component.resolution !== undefined && component.resolution > 0) {
|
|
273
|
+
text.resolution = component.resolution;
|
|
274
|
+
}
|
|
136
275
|
this.containerManager.getContainer(changed.gameObject.id).addChildAt(text, 0);
|
|
137
276
|
this.texts[changed.gameObject.id] = {
|
|
138
277
|
text,
|
|
139
278
|
component,
|
|
140
279
|
};
|
|
280
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
141
281
|
if (fontFamily) {
|
|
142
282
|
yield this.waitForFontResource(text, changed, fontFamily);
|
|
143
283
|
}
|
|
@@ -146,6 +286,7 @@ let Text = class Text extends Renderer {
|
|
|
146
286
|
addHTMLTextComponent(changed) {
|
|
147
287
|
return __awaiter(this, void 0, void 0, function* () {
|
|
148
288
|
const component = changed.component;
|
|
289
|
+
// 创建样式副本,先不设置 fontFamily
|
|
149
290
|
const styleWithoutFont = Object.assign({}, component.style);
|
|
150
291
|
const fontFamily = styleWithoutFont.fontFamily;
|
|
151
292
|
delete styleWithoutFont.fontFamily;
|
|
@@ -156,11 +297,15 @@ let Text = class Text extends Renderer {
|
|
|
156
297
|
text: htmlText,
|
|
157
298
|
component,
|
|
158
299
|
};
|
|
300
|
+
// 如果指定了字体资源,等待资源加载完成后设置 fontFamily
|
|
159
301
|
if (fontFamily) {
|
|
160
302
|
yield this.waitForFontResource(htmlText, changed, fontFamily);
|
|
161
303
|
}
|
|
162
304
|
});
|
|
163
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* 等待字体资源加载完成并更新文本
|
|
308
|
+
*/
|
|
164
309
|
waitForFontResource(text, changed, fontFamily) {
|
|
165
310
|
return __awaiter(this, void 0, void 0, function* () {
|
|
166
311
|
if (!fontFamily) {
|
|
@@ -168,13 +313,17 @@ let Text = class Text extends Renderer {
|
|
|
168
313
|
}
|
|
169
314
|
try {
|
|
170
315
|
const fontName = Array.isArray(fontFamily) ? fontFamily[0] : fontFamily;
|
|
316
|
+
// 通过 resource 系统获取字体资源
|
|
171
317
|
const asyncId = this.increaseAsyncId(changed.gameObject.id);
|
|
172
318
|
yield resource.getResource(fontName);
|
|
319
|
+
// 验证异步操作是否仍然有效(防止组件已被移除)
|
|
173
320
|
if (!this.validateAsyncId(changed.gameObject.id, asyncId))
|
|
174
321
|
return;
|
|
322
|
+
// 字体资源加载成功后,设置 fontFamily 并重新设置文本内容以触发重新渲染
|
|
175
323
|
const component = this.texts[changed.gameObject.id].component;
|
|
176
324
|
text.style.fontFamily = fontFamily;
|
|
177
325
|
text.text = component.text;
|
|
326
|
+
// 更新尺寸
|
|
178
327
|
}
|
|
179
328
|
catch (error) {
|
|
180
329
|
console.warn(`字体资源 ${fontFamily} 加载失败:`, error);
|
|
@@ -190,7 +339,15 @@ let Text = class Text extends Renderer {
|
|
|
190
339
|
else if (changed.prop.prop[0] === 'style') {
|
|
191
340
|
Object.assign(text.style, component.style);
|
|
192
341
|
}
|
|
342
|
+
else if (changed.prop.prop[0] === 'resolution' && !isHTMLText) {
|
|
343
|
+
// 更新 resolution
|
|
344
|
+
const textComponent = component;
|
|
345
|
+
if (textComponent.resolution !== undefined && textComponent.resolution > 0) {
|
|
346
|
+
text.resolution = textComponent.resolution;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
193
349
|
else if (changed.prop.prop[0] === 'textureStyle' && isHTMLText) {
|
|
350
|
+
// HTMLText 纹理样式变化需要重新创建
|
|
194
351
|
const htmlComponent = component;
|
|
195
352
|
const container = this.containerManager.getContainer(changed.gameObject.id);
|
|
196
353
|
const index = container.getChildIndex(text);
|
|
@@ -218,7 +375,7 @@ let Text = class Text extends Renderer {
|
|
|
218
375
|
Text.systemName = 'Text';
|
|
219
376
|
Text = __decorate([
|
|
220
377
|
decorators.componentObserver({
|
|
221
|
-
Text: ['text', { prop: ['style'], deep: true }],
|
|
378
|
+
Text: ['text', { prop: ['style'], deep: true }, 'resolution'],
|
|
222
379
|
HTMLText: ['text', { prop: ['style'], deep: true }, { prop: ['textureStyle'], deep: true }],
|
|
223
380
|
})
|
|
224
381
|
], 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
|
}
|