Files
esengine/packages/ui/src/components/UITextComponent.ts

345 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Component, ECSComponent, Property, Serializable, Serialize } from '@esengine/ecs-framework';
/**
* 文本对齐方式
* Text alignment options
*/
export type UITextAlign = 'left' | 'center' | 'right';
/**
* 文本垂直对齐方式
* Text vertical alignment options
*/
export type UITextVerticalAlign = 'top' | 'middle' | 'bottom';
/**
* 文本溢出处理
* Text overflow handling
*/
export type UITextOverflow = 'visible' | 'hidden' | 'ellipsis' | 'clip';
/**
* 字体粗细
* Font weight options
*/
export type UIFontWeight = 'normal' | 'bold' | 'lighter' | 'bolder' | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
/**
* UI 文本组件
* UI Text Component - Handles text rendering
*
* 定义文本内容和样式
* Defines text content and style
*/
@ECSComponent('UIText')
@Serializable({ version: 1, typeId: 'UIText' })
export class UITextComponent extends Component {
/**
* 文本内容
* Text content
*/
@Serialize()
@Property({ type: 'string', label: 'Text' })
public text: string = '';
// ===== 字体 Font =====
/**
* 字体大小(像素)
* Font size in pixels
*/
@Serialize()
@Property({ type: 'number', label: 'Font Size', min: 1 })
public fontSize: number = 14;
/**
* 字体族
* Font family
*/
@Serialize()
@Property({ type: 'string', label: 'Font Family' })
public fontFamily: string = 'Arial, sans-serif';
/**
* 字体粗细
* Font weight
*/
@Serialize()
@Property({
type: 'enum',
label: 'Font Weight',
options: [
{ value: 'normal', label: 'Normal' },
{ value: 'bold', label: 'Bold' },
{ value: 'lighter', label: 'Lighter' },
{ value: 'bolder', label: 'Bolder' }
]
})
public fontWeight: UIFontWeight = 'normal';
/**
* 是否斜体
* Whether italic
*/
@Serialize()
@Property({ type: 'boolean', label: 'Italic' })
public italic: boolean = false;
// ===== 颜色 Color =====
/**
* 文本颜色 (0xRRGGBB)
* Text color
*/
@Serialize()
@Property({ type: 'color', label: 'Color' })
public color: number = 0x000000;
/**
* 文本透明度
* Text alpha
*/
@Serialize()
@Property({ type: 'number', label: 'Alpha', min: 0, max: 1, step: 0.01 })
public alpha: number = 1;
// ===== 对齐 Alignment =====
/**
* 水平对齐
* Horizontal alignment
*/
@Serialize()
@Property({
type: 'enum',
label: 'Align',
options: [
{ value: 'left', label: 'Left' },
{ value: 'center', label: 'Center' },
{ value: 'right', label: 'Right' }
]
})
public align: UITextAlign = 'left';
/**
* 垂直对齐
* Vertical alignment
*/
@Serialize()
@Property({
type: 'enum',
label: 'Vertical Align',
options: [
{ value: 'top', label: 'Top' },
{ value: 'middle', label: 'Middle' },
{ value: 'bottom', label: 'Bottom' }
]
})
public verticalAlign: UITextVerticalAlign = 'middle';
// ===== 换行 Wrapping =====
/**
* 是否自动换行
* Whether to wrap text
*/
@Serialize()
@Property({ type: 'boolean', label: 'Word Wrap' })
public wordWrap: boolean = false;
/**
* 换行宽度0 = 使用父元素宽度)
* Wrap width (0 = use parent width)
*/
@Serialize()
@Property({ type: 'number', label: 'Wrap Width', min: 0 })
public wrapWidth: number = 0;
/**
* 行高倍数1 = 正常)
* Line height multiplier
*/
@Serialize()
@Property({ type: 'number', label: 'Line Height', min: 0.1, step: 0.1 })
public lineHeight: number = 1.2;
/**
* 字间距
* Letter spacing
*/
@Serialize()
@Property({ type: 'number', label: 'Letter Spacing' })
public letterSpacing: number = 0;
// ===== 溢出 Overflow =====
/**
* 文本溢出处理
* Text overflow handling
*/
@Property({
type: 'enum',
label: 'Overflow',
options: [
{ value: 'visible', label: 'Visible' },
{ value: 'hidden', label: 'Hidden' },
{ value: 'ellipsis', label: 'Ellipsis' },
{ value: 'clip', label: 'Clip' }
]
})
public overflow: UITextOverflow = 'visible';
/**
* 最大显示行数0 = 无限制)
* Maximum number of lines (0 = unlimited)
*/
@Property({ type: 'integer', label: 'Max Lines', min: 0 })
public maxLines: number = 0;
// ===== 装饰 Decoration =====
/**
* 下划线
* Underline
*/
@Property({ type: 'boolean', label: 'Underline' })
public underline: boolean = false;
/**
* 删除线
* Strikethrough
*/
@Property({ type: 'boolean', label: 'Strikethrough' })
public strikethrough: boolean = false;
// ===== 描边 Stroke =====
/**
* 描边宽度
* Stroke width
*/
@Property({ type: 'number', label: 'Stroke Width', min: 0 })
public strokeWidth: number = 0;
/**
* 描边颜色
* Stroke color
*/
@Property({ type: 'color', label: 'Stroke Color' })
public strokeColor: number = 0x000000;
// ===== 阴影 Shadow =====
/**
* 文本阴影启用
* Text shadow enabled
*/
@Property({ type: 'boolean', label: 'Shadow' })
public shadowEnabled: boolean = false;
/**
* 阴影 X 偏移
* Shadow X offset
*/
public shadowOffsetX: number = 1;
/**
* 阴影 Y 偏移
* Shadow Y offset
*/
public shadowOffsetY: number = 1;
/**
* 阴影颜色
* Shadow color
*/
public shadowColor: number = 0x000000;
/**
* 阴影透明度
* Shadow alpha
*/
public shadowAlpha: number = 0.5;
// ===== 计算属性 Computed =====
/**
* 计算后的文本行(由渲染系统填充)
* Computed text lines (filled by render system)
*/
public computedLines: string[] = [];
/**
* 计算后的文本宽度
* Computed text width
*/
public computedWidth: number = 0;
/**
* 计算后的文本高度
* Computed text height
*/
public computedHeight: number = 0;
/**
* 文本是否需要重新计算
* Whether text needs recomputation
*/
public dirty: boolean = true;
/**
* 设置文本
* Set text content
*/
public setText(text: string): this {
if (this.text !== text) {
this.text = text;
this.dirty = true;
}
return this;
}
/**
* 设置字体
* Set font properties
*/
public setFont(size: number, family?: string, weight?: UIFontWeight): this {
this.fontSize = size;
if (family !== undefined) this.fontFamily = family;
if (weight !== undefined) this.fontWeight = weight;
this.dirty = true;
return this;
}
/**
* 设置颜色
* Set text color
*/
public setColor(color: number, alpha: number = 1): this {
this.color = color;
this.alpha = alpha;
return this;
}
/**
* 获取 CSS 字体字符串
* Get CSS font string
*/
public getCSSFont(): string {
const style = this.italic ? 'italic ' : '';
const weight = typeof this.fontWeight === 'number' ? this.fontWeight : this.fontWeight;
return `${style}${weight} ${this.fontSize}px ${this.fontFamily}`;
}
/**
* 获取颜色的 CSS 字符串
* Get color as CSS string
*/
public getCSSColor(): string {
const r = (this.color >> 16) & 0xFF;
const g = (this.color >> 8) & 0xFF;
const b = this.color & 0xFF;
return `rgba(${r}, ${g}, ${b}, ${this.alpha})`;
}
}