rendx-engine 0.2.0

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.
@@ -0,0 +1,880 @@
1
+ import { vec2, mat2d } from 'gl-matrix';
2
+ import { AO, ClipPath, GF, Mat2d, Point, GradientOptions, IGraphicsRenderer, Size } from 'rendx-core';
3
+ import { BoundingBox } from 'rendx-bounding';
4
+ import { Path } from 'rendx-path';
5
+
6
+ type TransformStatus = 'start' | 'init' | 'waiting' | 'running' | 'last' | 'clear' | 'end';
7
+ /**
8
+ * 动画变换基类
9
+ * 统一管理 duration / delay / easing / repeat 和时间状态机
10
+ * 子类只需实现 apply(t) 方法
11
+ */
12
+ declare abstract class BaseTransform {
13
+ status: TransformStatus;
14
+ protected _duration: number;
15
+ protected _delay: number;
16
+ protected _easing: string;
17
+ protected _repeat: boolean;
18
+ protected _time: number;
19
+ /** 是否仍在活跃状态(未结束) */
20
+ get active(): boolean;
21
+ duration(time: number): this;
22
+ delay(time: number): this;
23
+ easing(easing: string): this;
24
+ repeat(repeat: boolean): this;
25
+ /** 子类实现具体的插值逻辑 */
26
+ protected abstract apply(t: number): void;
27
+ /** 动画结束时的清理,子类可覆盖 */
28
+ protected onEnd(): void;
29
+ interpolate(time: number): void;
30
+ }
31
+
32
+ interface TransformAttrs$1 {
33
+ translate?: [number, number, number, number];
34
+ rotate?: [number, number];
35
+ scale?: [number, number, number, number];
36
+ }
37
+ interface TransformValues {
38
+ tx: number;
39
+ ty: number;
40
+ sx: number;
41
+ sy: number;
42
+ rotate: number;
43
+ }
44
+ declare class GraphicsTransform extends BaseTransform {
45
+ V: TransformValues;
46
+ attrs: TransformAttrs$1;
47
+ values: Partial<TransformValues>;
48
+ constructor(values: TransformValues);
49
+ translate(x: number, y: number): this;
50
+ rotate(r: number): this;
51
+ scale(x: number, y: number): this;
52
+ protected apply(t: number): void;
53
+ protected onEnd(): void;
54
+ }
55
+
56
+ interface TransformAttrs {
57
+ opacity?: [number, number];
58
+ fill?: [string, string];
59
+ fillOpacity?: [number, number];
60
+ stroke?: [string, string];
61
+ strokeOpacity?: [number, number];
62
+ [key: string]: any;
63
+ }
64
+ declare class AttributeTransform extends BaseTransform {
65
+ V: AO;
66
+ attrs: TransformAttrs;
67
+ constructor(values: AO);
68
+ /** 设置属性动画目标值(属性应在调用前已设置初始值) */
69
+ attr(key: string, value: any): this;
70
+ protected apply(t: number): void;
71
+ }
72
+
73
+ /**
74
+ * 裁剪框动画,特有 init/clear 状态管理 clipPath 生命周期
75
+ * 覆盖基类 interpolate 实现自定义状态流
76
+ */
77
+ declare class ClipBoxTransform extends BaseTransform {
78
+ #private;
79
+ type: 'lr' | 'rl' | 'tb' | 'bt' | undefined;
80
+ boundingBox: BoundingBox | null;
81
+ clipPath: ClipPath;
82
+ constructor(clipPath: ClipPath);
83
+ direction(type: 'lr' | 'rl' | 'tb' | 'bt'): this;
84
+ box(box: BoundingBox): this;
85
+ protected apply(_t: number): void;
86
+ interpolate(time: number): void;
87
+ }
88
+
89
+ interface ArcTransformValues {
90
+ startAngle: number;
91
+ endAngle: number;
92
+ }
93
+ declare class ArcTransform extends BaseTransform {
94
+ V: ArcTransformValues;
95
+ attrs: Partial<Record<keyof ArcTransformValues, [number, number]>>;
96
+ values: Partial<ArcTransformValues>;
97
+ constructor(values: ArcTransformValues);
98
+ startAngle(a: number): this;
99
+ endAngle(a: number): this;
100
+ protected apply(t: number): void;
101
+ protected onEnd(): void;
102
+ }
103
+
104
+ interface SectorTransformValues {
105
+ startAngle: number;
106
+ endAngle: number;
107
+ innerRadius: number;
108
+ outerRadius: number;
109
+ }
110
+ declare class SectorTransform extends BaseTransform {
111
+ V: SectorTransformValues;
112
+ attrs: Partial<Record<keyof SectorTransformValues, [number, number]>>;
113
+ values: Partial<SectorTransformValues>;
114
+ constructor(values: SectorTransformValues);
115
+ startAngle(a: number): this;
116
+ endAngle(a: number): this;
117
+ innerRadius(r: number): this;
118
+ outerRadius(r: number): this;
119
+ protected apply(t: number): void;
120
+ protected onEnd(): void;
121
+ }
122
+
123
+ declare class SimulatedEvent {
124
+ #private;
125
+ type: string;
126
+ target: Graphics;
127
+ currentTarget: Graphics;
128
+ nativeEvent: Event;
129
+ eventPhase: number;
130
+ bubbles: boolean;
131
+ timestamp: number;
132
+ offsetX: number;
133
+ offsetY: number;
134
+ worldX: number;
135
+ worldY: number;
136
+ truth: boolean;
137
+ constructor(type: string, target: Graphics, nativeEvent: Event);
138
+ get captureType(): string;
139
+ stopPropagation(): void;
140
+ /** 返回从 target 到 root 的路径(缓存) */
141
+ composedPath(): Graphics[];
142
+ copy(): SimulatedEvent;
143
+ }
144
+
145
+ declare class EventDispatcher {
146
+ last: SimulatedEvent | null;
147
+ eventMap: Record<string, (event: SimulatedEvent) => void>;
148
+ constructor();
149
+ exec(event: SimulatedEvent, node: Graphics): void;
150
+ capture(event: SimulatedEvent): void;
151
+ target(event: SimulatedEvent): void;
152
+ bubble(event: SimulatedEvent): void;
153
+ flow(event: SimulatedEvent): void;
154
+ process(event: SimulatedEvent): void;
155
+ simulateEnter(event: SimulatedEvent): void;
156
+ simulateLeave(event: SimulatedEvent): void;
157
+ simulateOver(event: SimulatedEvent): void;
158
+ simulateOut(event: SimulatedEvent): void;
159
+ normal(event: SimulatedEvent): void;
160
+ onPointerEnter(event: SimulatedEvent): void;
161
+ onPointerLeave(event: SimulatedEvent): void;
162
+ onPointerOver(event: SimulatedEvent): void;
163
+ onPointerOut(event: SimulatedEvent): void;
164
+ clear(): void;
165
+ dispose(): void;
166
+ }
167
+
168
+ interface EventListenerOptions {
169
+ once?: boolean;
170
+ capture?: boolean;
171
+ }
172
+ type EventListener = (...args: any[]) => void;
173
+ declare class EventTarget {
174
+ #private;
175
+ dispatcher: EventDispatcher | null;
176
+ setDispatcher(dispatcher: EventDispatcher): void;
177
+ on(event: string, listener: EventListener, options?: EventListenerOptions): void;
178
+ off(event: string, listener: EventListener, options?: EventListenerOptions): void;
179
+ emit(event: string, payload?: any): void;
180
+ eventNames(): (string | symbol)[];
181
+ eventTypes(): string[];
182
+ listeners(event: string): ((...args: any[]) => void)[];
183
+ hasEvent(event: string): boolean;
184
+ dispatchEvent(evt: SimulatedEvent): void;
185
+ }
186
+
187
+ /**
188
+ * 场景图所有节点的基类。提供树操作、变换、脏标记、动画驱动等核心能力。
189
+ * type 编号:0=Graphics 基类,1=Scene,2=Group,3=Node,4=Layer
190
+ */
191
+ declare class Graphics extends EventTarget {
192
+ #private;
193
+ type: number;
194
+ uid: string;
195
+ name: string;
196
+ className: string;
197
+ parent: Graphics | null;
198
+ children: Graphics[];
199
+ z: number;
200
+ visible: boolean;
201
+ display: boolean;
202
+ pointerEvents: boolean;
203
+ autoVisible: boolean;
204
+ autoDisplay: boolean;
205
+ autoPointerEvents: boolean;
206
+ autoNeedUpdate: boolean;
207
+ autoWorldMatrixNeedUpdate: boolean;
208
+ needUpdate: boolean;
209
+ worldMatrixNeedUpdate: boolean;
210
+ data: AO;
211
+ ez: number;
212
+ dirty: boolean;
213
+ _translate: vec2;
214
+ _rotate: number;
215
+ _scale: vec2;
216
+ /** 当前平移值 [tx, ty](只读) */
217
+ get translation(): Readonly<vec2>;
218
+ /** 当前旋转弧度(只读) */
219
+ get rotation(): number;
220
+ /** 当前缩放值 [sx, sy](只读) */
221
+ get scaling(): Readonly<vec2>;
222
+ matrix: mat2d;
223
+ worldMatrix: mat2d;
224
+ transform: GraphicsTransform | null;
225
+ setName(name: string): this;
226
+ setClassName(className: string): this;
227
+ addClassName(className: string): this;
228
+ hasClassName(className: string): boolean;
229
+ setVisible(visible: boolean, bySelf?: boolean): this;
230
+ setDisplay(display: boolean, bySelf?: boolean): this;
231
+ setPointerEvents(pointerEvents: boolean, bySelf?: boolean): this;
232
+ setDirty(dirty: boolean): this;
233
+ /**
234
+ * 添加子节点。若 child 已有 parent 会先移除。
235
+ * @param child - 要添加的场景图节点
236
+ */
237
+ add(child: Graphics): this;
238
+ unshift(child: Graphics): this;
239
+ remove(child: Graphics): this;
240
+ removeChildren(): this;
241
+ is(name: string): boolean;
242
+ equals(target: Graphics): boolean;
243
+ /**
244
+ * 按名称查找子节点
245
+ * @param name - 节点名称
246
+ * @param deep - 是否递归搜索子树(默认 false 仅搜索直接children)
247
+ */
248
+ find(name: string, deep?: boolean): Graphics | null;
249
+ /**
250
+ * 按 className 查询节点列表
251
+ * @param className - CSS 风格的类名
252
+ * @param deep - 是否递归搜索子树
253
+ */
254
+ query(className: string, deep?: boolean): Graphics[];
255
+ has(name: string, deep?: boolean): boolean;
256
+ root(): Graphics;
257
+ /** 根到当前节点的完整路径(从 root 到 this) */
258
+ path(): Graphics[];
259
+ source(target: Graphics): boolean;
260
+ /** 深度优先遍历子树,包含自身 */
261
+ traverse(fn: GF): void;
262
+ setZ(z: number): this;
263
+ getZIndex(): number;
264
+ /**
265
+ * 设置本地矩阵(直接覆盖 translate/rotate/scale 计算的结果)
266
+ * @param matrix - [a, b, c, d, e, f] 2x3 仿射矩阵
267
+ * @param needUpdate - 是否触发世界矩阵更新(默认 true)
268
+ */
269
+ setMatrix(matrix: Mat2d, needUpdate?: boolean): this;
270
+ setWorldMatrix(matrix: Mat2d, needUpdate?: boolean): this;
271
+ /**
272
+ * 设置平移
273
+ * @param tx - X 方向平移量(像素)
274
+ * @param ty - Y 方向平移量(像素)
275
+ */
276
+ translate(tx: number, ty: number): this;
277
+ translateX(tx: number): this;
278
+ translateY(ty: number): this;
279
+ translateXY(tx: number, ty: number): this;
280
+ rotate(radian: number): this;
281
+ rotateZ(radian: number): this;
282
+ scale(sx: number, sy: number): this;
283
+ scaleX(sx: number): this;
284
+ scaleY(sy: number): this;
285
+ scaleXY(sx: number, sy: number): this;
286
+ /** 启用几何变换动画(GraphicsTransform),可链式配置 duration/delay/easing */
287
+ useTransform(): this;
288
+ renderable(): boolean;
289
+ /** 检查是否需要重绘(自身或子树有脏标记/更新标记) */
290
+ sign(): boolean;
291
+ tick(time: number): void;
292
+ update(): void;
293
+ clear(): void;
294
+ dispose(): void;
295
+ }
296
+
297
+ type ShapeCommand = 'text' | 'circle' | 'rect' | 'line' | 'path' | 'image' | '';
298
+ /**
299
+ * 图形形状基类。子类通过 from() 设置参数,build() 触发包围盒计算。
300
+ * command 指定渲染器的绘制方法:'text' | 'circle' | 'rect' | 'line' | 'path' | 'image'
301
+ */
302
+ declare class Shape {
303
+ uid: string;
304
+ type: number;
305
+ name: string;
306
+ command: ShapeCommand;
307
+ boundingBox: BoundingBox;
308
+ creator: Path | null;
309
+ d: string;
310
+ p: Path2D | null;
311
+ autoNeedUpdate: boolean;
312
+ needUpdate: boolean;
313
+ setBox(box: BoundingBox): void;
314
+ /** 按属性名列表获取值(序列化用),避免 as any */
315
+ getProps(keys: string[]): unknown[];
316
+ /** 接收节点属性(子类按需 override,如 TextShape 用于文本测量) */
317
+ setAttrs(_attrs: AO): void;
318
+ options(..._args: any[]): void;
319
+ /** 子类覆写此方法设置形状参数(如 CircleShape.from(cx, cy, r)) */
320
+ from(..._args: any[]): void;
321
+ /** 构建形状:计算包围盒和路径数据,仅在 needUpdate 时执行 */
322
+ build(): void;
323
+ /** 返回 SVG 路径字符串(d 属性) */
324
+ path(): string;
325
+ /** 返回缓存的 Path2D 对象(用于 Canvas 命中检测) */
326
+ path2d(): Path2D;
327
+ box(): BoundingBox;
328
+ useTransform(): this;
329
+ tick(_time: number): void;
330
+ /**
331
+ * 点命中检测(默认使用包围盒,子类可覆写用 path2d 精确检测)
332
+ * @param point - 本地坐标 [x, y]
333
+ */
334
+ hit(point: Point): boolean;
335
+ clear(): void;
336
+ dispose(): void;
337
+ }
338
+
339
+ /**
340
+ * 视觉属性容器,管理 fill/stroke/opacity/fontSize 等渲染属性。
341
+ * 支持属性动画(AttributeTransform)和裁剪动画(ClipBoxTransform)。
342
+ */
343
+ declare class Attributes {
344
+ #private;
345
+ uid: string;
346
+ name: string;
347
+ values: AO;
348
+ gradientOptions: GradientOptions | undefined;
349
+ clipPath: ClipPath | undefined;
350
+ autoNeedUpdate: boolean;
351
+ needUpdate: boolean;
352
+ transform: AttributeTransform | null;
353
+ clipBoxTransform: ClipBoxTransform | null;
354
+ set(key: string, value: any): this;
355
+ get(key: string): any;
356
+ /** 从对象批量设置属性(替换全部) */
357
+ from(attrs: AO): this;
358
+ /** 合并属性(保留已有值,追加新值) */
359
+ merge(attrs: AO): this;
360
+ /** 关联渐变配置 */
361
+ gradient(gradientOptions: GradientOptions): this;
362
+ /** 关联裁剪路径 */
363
+ clip(clipPath: ClipPath): this;
364
+ setBox(box: BoundingBox): this;
365
+ /** 启用属性动画(可对 opacity/fill/stroke 等做插值动画) */
366
+ useTransform(): this;
367
+ /** 启用裁剪框动画(lr/rl/tb/bt 方向的揭露动效) */
368
+ useClipBoxTransform(): this;
369
+ tick(time: number): this;
370
+ update(): void;
371
+ clear(): this;
372
+ dispose(): void;
373
+ }
374
+
375
+ declare function setCanvasRenderingContext2StrokeAttrs(ctx: OffscreenCanvasRenderingContext2D, attributes: AO): void;
376
+ declare const isHit: (path: Path2D, point: Point, fill: string, stroke: string, strokeAttrs?: AO) => boolean;
377
+
378
+ type ImageSource$1 = HTMLImageElement | ImageBitmap;
379
+ declare class ImageLoader {
380
+ #private;
381
+ /** 全局回调:任何图片加载完成时触发(用于重启渲染循环) */
382
+ onChange: (() => void) | null;
383
+ load(src: string, onReady?: () => void): ImageSource$1 | null;
384
+ get(src: string): ImageSource$1 | null;
385
+ has(src: string): boolean;
386
+ clear(): void;
387
+ }
388
+ declare const imageLoader: ImageLoader;
389
+
390
+ /**
391
+ * 叶子节点(type=3),场景图中的可渲染单元。
392
+ * 每个 Node 持有一个 Shape(几何形状)和一个 Attributes(视觉属性)。
393
+ *
394
+ * @example
395
+ * ```ts
396
+ * const node = Node.create('circle', { fill: 'red', stroke: '#000' });
397
+ * node.shape.from(100, 200, 50); // cx, cy, r
398
+ * node.translate(10, 20);
399
+ * scene.add(node);
400
+ * ```
401
+ */
402
+ declare class Node extends Graphics {
403
+ #private;
404
+ type: number;
405
+ /** Shape 注册类型名(如 'rect', 'circle' 等),序列化时使用 */
406
+ shapeType: string;
407
+ shape: Shape;
408
+ attrs: Attributes;
409
+ /**
410
+ * 创建指定类型的节点(推荐使用此工厂方法而非直接 new)
411
+ * @param type - 形状类型:'circle' | 'rect' | 'line' | 'path' | 'text' | 'image'
412
+ * @param values - 视觉属性(fill/stroke/opacity/fontSize 等)
413
+ */
414
+ static create(type: string, values?: AO): Node;
415
+ constructor(shape: Shape, attrs: Attributes);
416
+ tick(time: number): void;
417
+ update(): void;
418
+ sign(): boolean;
419
+ /**
420
+ * 计算节点在世界坐标系中的轴对齐包围盒 (AABB)。
421
+ * 通过 worldMatrix 变换本地 boundingBox 的四个角点,
422
+ * 返回变换后的包围盒。若本地包围盒不可用,返回 null。
423
+ */
424
+ getWorldBBox(): BoundingBox | null;
425
+ /**
426
+ * 命中检测:将屏幕坐标通过逆世界矩阵变换为本地坐标,然后检测是否命中
427
+ * @param point - 场景坐标 [x, y]
428
+ * @returns 命中时返回自身,否则 undefined
429
+ */
430
+ hit(point: Point): this | undefined;
431
+ }
432
+
433
+ interface RendererConfig {
434
+ width: number;
435
+ height: number;
436
+ renderer?: 'svg' | 'canvas' | IGraphicsRenderer;
437
+ viewport?: [number, number, number, number];
438
+ }
439
+ declare class Renderer {
440
+ #private;
441
+ cfg: RendererConfig;
442
+ viewMatrix: mat2d;
443
+ constructor(cfg: Partial<RendererConfig>);
444
+ get el(): HTMLCanvasElement | SVGSVGElement;
445
+ /** 客户端坐标(clientX/Y) → 画布局部坐标 */
446
+ position(point: Point): Point;
447
+ resize(size: Size): void;
448
+ /** 绘制渲染队列 */
449
+ draw(queue: Node[]): void;
450
+ clear(): void;
451
+ dispose(): void;
452
+ }
453
+
454
+ /** 分组容器节点(type=2),不可渲染,用于组织场景图层级 */
455
+ declare class Group extends Graphics {
456
+ type: number;
457
+ }
458
+
459
+ /**
460
+ * Layer — 分层渲染节点
461
+ * 每个 Layer 持有独立 Renderer(独立 Canvas/SVG 元素),实现多 Canvas 分层渲染。
462
+ * Layer 本身是 Group 子类,节点通过 layer.add(node) 挂入层中。
463
+ */
464
+ declare class Layer extends Group {
465
+ #private;
466
+ type: number;
467
+ /** 层名称 */
468
+ layerName: string;
469
+ /** 层级序号(CSS z-index) */
470
+ layerIndex: number;
471
+ /** 独立渲染器 */
472
+ renderer: Renderer;
473
+ /** 是否为内置事件层(不可删除,不渲染内容) */
474
+ isEventLayer: boolean;
475
+ /** 是否启用视口裁剪(默认 true,Text 层等可关闭) */
476
+ culling: boolean;
477
+ constructor(name: string, index: number, cfg: Partial<RendererConfig>, isEventLayer?: boolean);
478
+ /** 获取当前层的渲染队列(仅 type=3 的 Node) */
479
+ getQueue(): Node[];
480
+ /** 层级是否需要重绘 */
481
+ sign(): boolean;
482
+ /** 绘制本层 */
483
+ draw(): void;
484
+ resize(size: {
485
+ width: number;
486
+ height: number;
487
+ }): void;
488
+ clear(): void;
489
+ dispose(): void;
490
+ }
491
+
492
+ /** 场景根节点(type=1),管理所有渲染层、提供命中检测和坐标映射 */
493
+ declare class Scene extends Graphics {
494
+ #private;
495
+ type: number;
496
+ /** 有序层列表(按 layerIndex 排序) */
497
+ layers: Layer[];
498
+ /** 注册一个 Layer(由 App 调用) */
499
+ registerLayer(layer: Layer): void;
500
+ /** 按名称获取 Layer */
501
+ getLayer(name: string): Layer | undefined;
502
+ /** 移除 Layer(事件层不可移除) */
503
+ removeLayer(name: string): void;
504
+ /**
505
+ * 默认 add:添加到 default 层(向下兼容)
506
+ * 如果没有 layer,退回原行为(直接加到 Scene children)
507
+ */
508
+ add(child: Graphics): this;
509
+ /** 收集所有可渲染节点(type=3),按 ez 排序,带脏标记缓存 */
510
+ getQueue(): Node[];
511
+ /** 跨层命中检测:从最高层向下搜索 */
512
+ pick(point: Point): Node | undefined;
513
+ /**
514
+ * 屏幕坐标 → 场景坐标(通过逆 worldMatrix 变换,缓存逆矩阵)
515
+ * @param point - 画布像素坐标 [x, y]
516
+ */
517
+ position(point: Point): Point;
518
+ setMatrix(matrix: Mat2d, needUpdate?: boolean): this;
519
+ }
520
+
521
+ declare class SymbolShape extends Shape {
522
+ command: "path";
523
+ r: number;
524
+ symbol: string;
525
+ options(symbol: string): void;
526
+ from(r: number): void;
527
+ build(): void;
528
+ path(): string;
529
+ box(): BoundingBox;
530
+ }
531
+
532
+ declare class RoundShape extends Shape {
533
+ command: "path";
534
+ x: number;
535
+ y: number;
536
+ width: number;
537
+ height: number;
538
+ rx: number | number[] | undefined;
539
+ ry: number | number[] | undefined;
540
+ options(rx: number | number[] | undefined, ry?: number | number[] | undefined): void;
541
+ from(x: number, y: number, width: number, height: number): void;
542
+ build(): void;
543
+ path(): string;
544
+ box(): BoundingBox;
545
+ }
546
+
547
+ declare class CurveShape extends Shape {
548
+ command: "path";
549
+ segments: Point[][];
550
+ curve: string;
551
+ closed: boolean;
552
+ options(curve: string, closed: boolean): void;
553
+ from(segments: Point[][]): void;
554
+ build(): void;
555
+ path(): string;
556
+ box(): BoundingBox;
557
+ }
558
+
559
+ declare class AreaShape extends Shape {
560
+ command: "path";
561
+ upperSegments: Point[][];
562
+ lowerSegments: Point[][];
563
+ curve: string;
564
+ options(curve: string): void;
565
+ from(upperSegments: Point[][], lowerSegments: Point[][]): void;
566
+ build(): void;
567
+ path(): string;
568
+ box(): BoundingBox;
569
+ }
570
+
571
+ declare class PolygonShape extends Shape {
572
+ command: "path";
573
+ points: Point[];
574
+ curve: string;
575
+ closed: boolean;
576
+ options(curve: string, closed?: boolean): void;
577
+ from(points: Point[]): void;
578
+ build(): void;
579
+ path(): string;
580
+ box(): BoundingBox;
581
+ }
582
+
583
+ declare class SectorShape extends Shape {
584
+ command: "path";
585
+ r: number;
586
+ startAngle: number;
587
+ endAngle: number;
588
+ padAngle: number | undefined;
589
+ innerRadius: number;
590
+ outerRadius: number;
591
+ rc: number | number[] | undefined;
592
+ transform: SectorTransform | null;
593
+ options(rc: number | number[] | undefined): void;
594
+ from(r: number, startAngle: number, endAngle: number, innerRadius: number, outerRadius: number, padAngle?: number): void;
595
+ build(): void;
596
+ path(): string;
597
+ box(): BoundingBox;
598
+ useTransform(): this;
599
+ tick(time: number): this;
600
+ }
601
+
602
+ declare class ArcShape extends Shape {
603
+ command: "path";
604
+ r: number;
605
+ startAngle: number;
606
+ endAngle: number;
607
+ radius: number;
608
+ transform: ArcTransform | null;
609
+ from(r: number, startAngle: number, endAngle: number, radius: number): void;
610
+ build(): void;
611
+ path(): string;
612
+ box(): BoundingBox;
613
+ useTransform(): this;
614
+ tick(time: number): this;
615
+ }
616
+
617
+ declare class PathShape extends Shape {
618
+ command: "path";
619
+ from(d: string): void;
620
+ }
621
+
622
+ /**
623
+ * 文本测量函数签名。
624
+ * 接收文本内容和节点样式属性(含 fontSize、fontFamily 等),返回本地空间 BoundingBox。
625
+ * 返回 null 表示无法测量。
626
+ */
627
+ type TextMeasureFn = (text: string, attrs: AO) => BoundingBox | null;
628
+ /** 文本形状,支持自定义测量函数计算包围盒 */
629
+ declare class TextShape extends Shape {
630
+ #private;
631
+ command: "text";
632
+ x: number;
633
+ y: number;
634
+ text: string;
635
+ /**
636
+ * 全局默认文本测量函数。
637
+ * 使用者通过 `TextShape.defaultMeasure = fn` 注入,
638
+ * 所有 TextShape 实例默认使用此函数(除非实例级覆盖)。
639
+ *
640
+ * @example
641
+ * ```ts
642
+ * import {getTextBoundingBox} from 'rendx-dom';
643
+ * TextShape.defaultMeasure = (text, attrs) =>
644
+ * getTextBoundingBox({fontSize: attrs.fontSize, fontFamily: attrs.fontFamily}, text);
645
+ * ```
646
+ */
647
+ static defaultMeasure: TextMeasureFn | null;
648
+ /** 实例级文本测量函数,优先于 `defaultMeasure` */
649
+ measure: TextMeasureFn | null;
650
+ setAttrs(attrs: AO): void;
651
+ from(text: string, x: number, y: number): void;
652
+ build(): void;
653
+ box(): BoundingBox;
654
+ hit(_point: Point): boolean;
655
+ }
656
+
657
+ /** 线段形状 */
658
+ declare class LineShape extends Shape {
659
+ command: "line";
660
+ x1: number;
661
+ y1: number;
662
+ x2: number;
663
+ y2: number;
664
+ /**
665
+ * 设置线段端点
666
+ * @param x1 - 起点 X
667
+ * @param y1 - 起点 Y
668
+ * @param x2 - 终点 X
669
+ * @param y2 - 终点 Y
670
+ */
671
+ from(x1: number, y1: number, x2: number, y2: number): void;
672
+ path2d(): Path2D;
673
+ box(): BoundingBox;
674
+ }
675
+
676
+ /** 矩形形状 */
677
+ declare class RectShape extends Shape {
678
+ command: "rect";
679
+ x: number;
680
+ y: number;
681
+ width: number;
682
+ height: number;
683
+ /**
684
+ * 设置矩形参数
685
+ * @param x - 左上角 X
686
+ * @param y - 左上角 Y
687
+ * @param width - 宽度
688
+ * @param height - 高度
689
+ */
690
+ from(x: number, y: number, width: number, height: number): void;
691
+ hit(point: Point): boolean;
692
+ box(): BoundingBox;
693
+ }
694
+
695
+ /** 圆形形状,用于 Scene Graph 中的圆形节点 */
696
+ declare class CircleShape extends Shape {
697
+ command: "circle";
698
+ cx: number;
699
+ cy: number;
700
+ r: number;
701
+ /**
702
+ * 设置圆形参数
703
+ * @param cx - 圆心 X
704
+ * @param cy - 圆心 Y
705
+ * @param r - 半径
706
+ */
707
+ from(cx: number, cy: number, r: number): void;
708
+ hit(point: Point): boolean;
709
+ box(): BoundingBox;
710
+ }
711
+
712
+ type ImageSource = HTMLImageElement | ImageBitmap;
713
+ declare class ImageShape extends Shape {
714
+ command: "image";
715
+ src: string;
716
+ x: number;
717
+ y: number;
718
+ width: number;
719
+ height: number;
720
+ source: ImageSource | null;
721
+ from(src: string, x: number, y: number, width: number, height: number): this;
722
+ /** 直接传入已加载的图片对象(跳过 loader) */
723
+ fromElement(el: ImageSource, x: number, y: number, width: number, height: number): this;
724
+ hit(point: Point): boolean;
725
+ box(): BoundingBox;
726
+ }
727
+
728
+ declare const createShape: (type: string) => Shape;
729
+
730
+ declare class EventObserver {
731
+ #private;
732
+ feats: Record<string, boolean>;
733
+ scene: Scene;
734
+ renderer: Renderer;
735
+ dispatcher: EventDispatcher;
736
+ constructor(scene: Scene, renderer: Renderer);
737
+ /** 幂等绑定:每种原生事件只注册一次 */
738
+ bindEvents(): void;
739
+ unbindEvents(): void;
740
+ dispose(): void;
741
+ }
742
+
743
+ interface RendxJSON {
744
+ version: 1;
745
+ width: number;
746
+ height: number;
747
+ layers: LayerJSON[];
748
+ }
749
+ interface LayerJSON {
750
+ name: string;
751
+ index: number;
752
+ culling?: boolean;
753
+ children: ChildJSON[];
754
+ }
755
+ type ChildJSON = NodeJSON | GroupJSON;
756
+ interface GraphicsJSON {
757
+ name?: string;
758
+ className?: string;
759
+ z?: number;
760
+ visible?: boolean;
761
+ display?: boolean;
762
+ translate?: [number, number];
763
+ rotate?: number;
764
+ scale?: [number, number];
765
+ data?: AO;
766
+ }
767
+ interface NodeJSON extends GraphicsJSON {
768
+ type: 'node';
769
+ shapeType: string;
770
+ args: unknown[];
771
+ options?: unknown[];
772
+ attrs?: AO;
773
+ gradient?: GradientOptions;
774
+ clipPath?: ClipPath;
775
+ }
776
+ interface GroupJSON extends GraphicsJSON {
777
+ type: 'group';
778
+ children: ChildJSON[];
779
+ }
780
+ declare function serializeLayer(layer: Layer): LayerJSON;
781
+ /** 序列化整个 App 场景为 JSON */
782
+ declare function serialize(layers: Layer[], width: number, height: number): RendxJSON;
783
+ /** 从 JSON 反序列化,创建层和节点(不包含 App 实例) */
784
+ declare function deserialize(json: RendxJSON, cfg: Partial<RendererConfig>): Layer[];
785
+
786
+ /**
787
+ * 插件接口
788
+ *
789
+ * 插件通过 `app.use(plugin)` 注册,框架会调用 `install(app)` 完成初始化。
790
+ * 当 App dispose 时,若插件提供了 `dispose` 方法,则会自动调用。
791
+ */
792
+ interface Plugin {
793
+ /** 插件名称(用于去重和调试) */
794
+ name: string;
795
+ /** 安装插件,在 `app.use()` 时调用 */
796
+ install(app: App): void;
797
+ /** 当 App resize 时调用 */
798
+ resize?(width: number, height: number): void;
799
+ /** 卸载插件,在 `app.dispose()` 时自动调用 */
800
+ dispose?(): void;
801
+ }
802
+
803
+ interface AppConfig extends RendererConfig {
804
+ layers?: string[];
805
+ /** 是否监听容器尺寸变化自动 resize(默认 false) */
806
+ autoResize?: boolean;
807
+ }
808
+ /**
809
+ * Rendx 引擎顶层控制器,负责场景、渲染层、事件和插件的统一管理。
810
+ *
811
+ * @example
812
+ * ```ts
813
+ * const app = new App({ width: 800, height: 600 });
814
+ * app.mount(document.getElementById('container')!);
815
+ *
816
+ * const circle = Node.create('circle', { fill: '#f00' });
817
+ * circle.shape.from(400, 300, 50);
818
+ * app.scene.add(circle);
819
+ * app.render();
820
+ * ```
821
+ */
822
+ declare class App {
823
+ #private;
824
+ cfg: AppConfig;
825
+ scene: Scene;
826
+ observer: EventObserver;
827
+ /** 挂载容器(供插件访问) */
828
+ get container(): HTMLDivElement | null;
829
+ /** 是否已挂载 */
830
+ get mounted(): boolean;
831
+ /**
832
+ * @param cfg - 引擎配置(width/height/layers/autoResize 等)
833
+ */
834
+ constructor(cfg?: Partial<AppConfig>);
835
+ /**
836
+ * 挂载到 DOM 容器,初始化渲染层并绑定事件。必须在 render() 之前调用。
837
+ * @param container - 目标 DOM 元素,引擎会在其中创建 Canvas 元素
838
+ */
839
+ mount(container: HTMLElement): this;
840
+ /** 添加渲染层 */
841
+ addLayer(name: string, index: number): Layer;
842
+ /** 获取层 */
843
+ getLayer(name: string): Layer | undefined;
844
+ /**
845
+ * 注册插件(同名插件不会重复注册)
846
+ * @param plugin - 实现 Plugin 接口的插件实例
847
+ */
848
+ use(plugin: Plugin): this;
849
+ /** 获取已注册的插件 */
850
+ getPlugin(name: string): Plugin | undefined;
851
+ /** 同步渲染一帧。适用于静态内容,仅重绘脏层 */
852
+ render(): void;
853
+ /** 请求异步渲染循环(rAF),有动画时自动继续,无变化时停止 */
854
+ requestRender(): void;
855
+ /**
856
+ * 调整画布尺寸,同步更新所有层、容器和视口矩阵
857
+ * @param width - 新宽度(像素)
858
+ * @param height - 新高度(像素)
859
+ */
860
+ resize(width: number, height: number): void;
861
+ clear(): void;
862
+ dispose(): void;
863
+ /** 将所有渲染层合成到一个 Canvas 上并返回 */
864
+ toCanvas(): HTMLCanvasElement;
865
+ /** 序列化所有渲染层的场景图为 JSON,可用于保存/回放 */
866
+ toJSON(): RendxJSON;
867
+ /**
868
+ * 从 JSON 快照创建新的 App 实例(静态工厂方法)
869
+ * @param json - 由 toJSON() 生成的场景快照
870
+ * @param cfg - 可选的额外配置(会与 json 中的 width/height 合并)
871
+ */
872
+ static fromJSON(json: RendxJSON, cfg?: Partial<AppConfig>): App;
873
+ /**
874
+ * 将 JSON 快照恢复到当前 App 实例(就地替换所有渲染层内容)。
875
+ * 与静态 fromJSON 不同,此方法不创建新 App,保留挂载状态和插件。
876
+ */
877
+ restoreFromJSON(json: RendxJSON): void;
878
+ }
879
+
880
+ export { App, type AppConfig, ArcShape, ArcTransform, AreaShape, AttributeTransform, Attributes, BaseTransform, type ChildJSON, CircleShape, ClipBoxTransform, CurveShape, EventDispatcher, type EventListener, type EventListenerOptions, EventObserver, EventTarget, Graphics, type GraphicsJSON, GraphicsTransform, Group, type GroupJSON, ImageShape, Layer, type LayerJSON, LineShape, Node, type NodeJSON, PathShape, type Plugin, PolygonShape, RectShape, Renderer, type RendererConfig, type RendxJSON, RoundShape, Scene, SectorShape, SectorTransform, Shape, type ShapeCommand, SimulatedEvent, SymbolShape, type TextMeasureFn, TextShape, type TransformStatus, createShape, deserialize, imageLoader, isHit, serialize, serializeLayer, setCanvasRenderingContext2StrokeAttrs };