modern-canvas 0.26.2 → 0.27.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.
@@ -16,6 +16,13 @@ export interface Node2D {
16
16
  export declare class Node2D extends CanvasItem {
17
17
  rotation: number;
18
18
  readonly position: Vector2;
19
+ /**
20
+ * Scroll/content offset (in this node's local space) applied only to its
21
+ * children's global transform — the node's own transform, globalAabb and
22
+ * overflow-clip box are unaffected. Runtime UI state, not serialized: lets a
23
+ * frame scroll its overflowing content while its clip box stays put.
24
+ */
25
+ readonly contentOffset: Vector2;
19
26
  readonly scale: Vector2;
20
27
  readonly skew: Vector2;
21
28
  readonly pivot: Vector2;
@@ -1,6 +1,6 @@
1
1
  import type { Background, Chart, CommentThread, Connection, Display, Fill, Foreground, NormalizedFilter, Outline, Shadow, Shape, Table, Text } from 'modern-idoc';
2
2
  import type { Path2D, Vector2Like } from 'modern-path2d';
3
- import type { InputEvent, InputEventKey } from '../../../core';
3
+ import type { InputEvent, InputEventKey, WebGLRenderer } from '../../../core';
4
4
  import type { Node, Rectangulable, RectangulableEvents, SceneTree, Viewport } from '../../main';
5
5
  import type { Node2DEvents, Node2DProperties } from '../Node2D';
6
6
  import type { Element2DStyleProperties } from './Element2DStyle';
@@ -46,6 +46,29 @@ export interface Element2DProperties extends Node2DProperties {
46
46
  /** 元素级结构化滤镜(Effect.filter),转成 CSS filter 后与 style.filter 合并 */
47
47
  filter: NormalizedFilter;
48
48
  }
49
+ interface ScrollThumb {
50
+ x: number;
51
+ y: number;
52
+ w: number;
53
+ h: number;
54
+ travel: number;
55
+ span: number;
56
+ min: number;
57
+ }
58
+ export interface ScrollRange {
59
+ x: {
60
+ min: number;
61
+ max: number;
62
+ };
63
+ y: {
64
+ min: number;
65
+ max: number;
66
+ };
67
+ content: {
68
+ w: number;
69
+ h: number;
70
+ };
71
+ }
49
72
  export declare class Element2D extends Node2D implements Rectangulable {
50
73
  readonly flexbox: Flexbox;
51
74
  readonly aabb: Aabb2D;
@@ -56,6 +79,21 @@ export declare class Element2D extends Node2D implements Rectangulable {
56
79
  readonly size: Vector2;
57
80
  protected _allowPointerEvents: boolean;
58
81
  protected _overflowHidden: boolean;
82
+ protected _scrollbarMode?: 'scroll' | 'auto';
83
+ protected _pointerInside: boolean;
84
+ protected _scrollbarHoverAxis?: 'x' | 'y';
85
+ protected _scrollbarDrag?: {
86
+ axis: 'x' | 'y';
87
+ startScreen: number;
88
+ startOffset: number;
89
+ travel: number;
90
+ span: number;
91
+ min: number;
92
+ };
93
+ protected _scrollThumbCache: Record<'v' | 'h', {
94
+ key: string;
95
+ batchable: any;
96
+ } | undefined>;
59
97
  protected _style: Element2DStyle;
60
98
  get style(): Element2DStyle;
61
99
  set style(value: Element2DProperties['style'] | undefined);
@@ -142,9 +180,32 @@ export declare class Element2D extends Node2D implements Rectangulable {
142
180
  getGlobalObb(): Obb2D;
143
181
  protected _draw(): void;
144
182
  protected _drawContent(): void;
183
+ protected _scrollRangeCache?: {
184
+ rev: number;
185
+ value: ScrollRange | undefined;
186
+ };
187
+ /**
188
+ * 内容(子节点本地 AABB 并集)相对自身 box 的可滚动区间。用于滚动条与滚轮:
189
+ * offset>0 表示内容上/左移、露出下/右侧内容。无子节点返回 undefined。
190
+ *
191
+ * 按全局 geometryRevision 缓存(与连线 route 缓存同款):同一帧内滚轮 handler /
192
+ * render / thumb 命中检测会多次调用,宿主(如 mce)还经 reactive proxy 访问——
193
+ * 子节点上千时每次遍历是数千次 proxy 读,缓存命中则一次都不发生。
194
+ */
195
+ getScrollRange(): ScrollRange | undefined;
196
+ protected _computeScrollRange(): ScrollRange | undefined;
197
+ protected _scrollThumbs(zx: number, zy: number): {
198
+ v?: ScrollThumb;
199
+ h?: ScrollThumb;
200
+ } | undefined;
201
+ protected _scrollViewport(): Viewport | undefined;
202
+ render(renderer: WebGLRenderer, next?: () => void): void;
203
+ protected _drawScrollThumb(renderer: WebGLRenderer, slot: 'v' | 'h', r: ScrollThumb, active: boolean): void;
204
+ protected _scrollbarInput(event: InputEvent, key: InputEventKey): boolean;
145
205
  input(event: InputEvent, key: InputEventKey): void;
146
206
  protected _positionInput(localPos: Vector2Like, key: InputEventKey): boolean;
147
207
  protected _input(event: InputEvent, key: InputEventKey): void;
148
208
  toJSON(): Record<string, any>;
149
209
  protected _destroy(): void;
150
210
  }
211
+ export {};
@@ -14,10 +14,57 @@ export declare class Element2DConnection extends CoreObject implements Normalize
14
14
  labelPosition: number;
15
15
  protected _routeSig?: string;
16
16
  protected _routePath?: Path2D;
17
+ protected _keyTargets: (Element2D | undefined)[];
18
+ protected _routeKey: number[];
19
+ protected _keyMode?: ConnectionMode;
20
+ protected _keyAnchors: (string | number | undefined)[];
21
+ protected _keyRevision: number;
22
+ protected _keyValid: boolean;
23
+ protected _anchorsSet: boolean;
24
+ protected _startTarget?: Element2D;
25
+ protected _endTarget?: Element2D;
26
+ protected _targetsRevision: number;
27
+ protected _targetsStartId?: string;
28
+ protected _targetsEndId?: string;
17
29
  constructor(_parent: Element2D);
18
30
  setProperties(properties?: Record<string, any>): this;
31
+ /**
32
+ * Whether this element *is* a connection — i.e. it declares at least one anchor.
33
+ * Says nothing about whether those anchors still resolve; callers use this to tell
34
+ * connection elements apart from ordinary ones (hit-testing, marquee selection,
35
+ * cascade-deleting dangling lines), and a dangling connection is still a connection.
36
+ *
37
+ * For "can this actually be routed right now", see {@link isRoutable}.
38
+ */
19
39
  isValid(): boolean;
40
+ /**
41
+ * Whether at least one anchor resolves to a node currently in the tree. A connection
42
+ * whose targets were removed is valid but not routable: it must stop consuming a
43
+ * per-frame route and stop opting out of viewport culling.
44
+ */
45
+ isRoutable(): boolean;
20
46
  protected _updateProperty(key: string, value: any, oldValue: any): void;
47
+ protected _resolveTarget(anchor: NormalizedConnection['start']): Element2D | undefined;
48
+ /**
49
+ * Re-resolve both anchors, at most once per (revision, anchor ids) pair. Nodes enter
50
+ * and leave the tree through `SceneTree`, which bumps the revision, so a cached target
51
+ * can never outlive its membership.
52
+ */
53
+ protected _refreshTargets(): void;
54
+ /**
55
+ * The anchors are compared by value rather than relying on `_updateProperty`, because
56
+ * `connection.start.idx = 2` mutates in place without going through the setter.
57
+ */
58
+ protected _anchorsMatch(): boolean;
59
+ /**
60
+ * Everything an endpoint's world point + direction is derived from, compared in place.
61
+ * `getNodeById<Element2D>` is an unchecked cast — a connection may well point at a
62
+ * plain Node2D — so every field is read defensively.
63
+ */
64
+ protected _keyMatches(target: Element2D | undefined, offset: number): boolean;
65
+ protected _writeKey(target: Element2D | undefined, offset: number): void;
66
+ /** Snapshot what the current route was computed from. Only on a cache miss. */
67
+ protected _storeKey(s: Element2D | undefined, e: Element2D | undefined): void;
21
68
  /**
22
69
  * Resolve an anchor to a world-space point.
23
70
  * If idx is specified, uses the target shape's connectionPoints;
@@ -29,7 +76,7 @@ export declare class Element2DConnection extends CoreObject implements Normalize
29
76
  * Direction comes from the connection point's `ang` if present, otherwise it is
30
77
  * inferred from which edge the point sits on; a centre fallback has no direction.
31
78
  */
32
- resolveEndpoint(anchor: NormalizedConnection['start']): ConnectionEndpoint | undefined;
79
+ resolveEndpoint(anchor: NormalizedConnection['start'], target?: Element2D | undefined): ConnectionEndpoint | undefined;
33
80
  /**
34
81
  * World-space point at the configured {@link labelPosition} along the current
35
82
  * route — handy for anchoring an external label / badge to the line. Returns
@@ -9,6 +9,17 @@ export declare class Element2DOutline extends Element2DFill implements Normalize
9
9
  lineJoin: NormalizedOutline['lineJoin'];
10
10
  headEnd?: HeadEnd;
11
11
  tailEnd?: TailEnd;
12
+ /**
13
+ * 描边流动效果速度(周期/秒,符号=方向,0/undefined=关闭)。运行时 UI 态
14
+ * (internal:不进 toJSON / setProperties,不会被序列化或协同同步),供
15
+ * hover/激活时给连线加「能量流动」效果。
16
+ */
17
+ flow?: number;
18
+ /**
19
+ * 描边宽度的运行时倍率(internal,不序列化)。hover 加粗等纯 UI 反馈用,
20
+ * 不改动文档里的 width;1/undefined = 不加粗。
21
+ */
22
+ widthBoost?: number;
12
23
  setProperties(properties?: Outline): this;
13
24
  protected _updateProperty(key: string, value: any, oldValue: any): void;
14
25
  isValid(): boolean;
@@ -11,6 +11,12 @@ export declare class Element2DShape extends CoreObject implements NormalizedShap
11
11
  viewBox: NormalizedShape['viewBox'];
12
12
  paths: NormalizedShape['paths'];
13
13
  connectionPoints: NormalizedShape['connectionPoints'];
14
+ /**
15
+ * Bumped whenever `connectionPoints` is replaced. Connections use it to tell
16
+ * whether their anchors moved without re-resolving them every frame.
17
+ * Mutating the array in place doesn't bump it — same as every other property.
18
+ */
19
+ connectionPointsDirtyId: number;
14
20
  protected _path2DSet: Path2DSet;
15
21
  /**
16
22
  * A derived path in the element's local pixel space (NOT normalized to the unit
@@ -20,6 +20,8 @@ export interface StrokeDraw extends Partial<CanvasBatchable> {
20
20
  type: 'stroke';
21
21
  path: Path2D;
22
22
  lineStyle: LineStyle;
23
+ /** 流动速度(周期/秒,符号=方向);发射 batchable 时经 encodeFlowSpeed 编成 effectParam。 */
24
+ flow?: number;
23
25
  }
24
26
  export interface FillDraw extends Partial<CanvasBatchable> {
25
27
  type: 'fill';
@@ -41,6 +43,8 @@ export declare class CanvasContext extends Path2D {
41
43
  lineJoin?: LineJoin;
42
44
  lineWidth?: number;
43
45
  miterLimit?: number;
46
+ /** 描边流动效果速度(周期/秒,符号=方向;0/undefined=关闭)。见 flowStreakEffect。 */
47
+ lineFlow?: number;
44
48
  transformUv?: TransformUv;
45
49
  transformVertex?: TransformVertex;
46
50
  protected _draws: (StrokeDraw | FillDraw | MeshDraw)[];
@@ -48,6 +52,7 @@ export declare class CanvasContext extends Path2D {
48
52
  sig: string;
49
53
  vertices: Float32Array;
50
54
  indices: Uint32Array;
55
+ uvs?: Float32Array;
51
56
  }[];
52
57
  protected _parseDrawStyle(source?: ColorValue | Texture2D): {
53
58
  texture?: Texture2D;
@@ -26,6 +26,7 @@ export interface SceneTree {
26
26
  }
27
27
  export interface SceneTreeProperties extends MainLoopProperties {
28
28
  msaa: boolean;
29
+ fxaa: boolean;
29
30
  pixelate: boolean;
30
31
  roundPixels: boolean;
31
32
  backgroundColor: Hex8Color;
@@ -36,6 +37,12 @@ export interface SceneTreeProperties extends MainLoopProperties {
36
37
  }
37
38
  export declare class SceneTree extends MainLoop {
38
39
  msaa: boolean;
40
+ /** 最终合成时做 FXAA 后处理(零额外 pass / 显存,MSAA 之外的轻量抗锯齿路线)。 */
41
+ fxaa: boolean;
42
+ /** 描边流动效果的高亮色(如主题主色);见 Element2DOutline.flow。 */
43
+ flowColor?: Hex8Color;
44
+ /** 流动亮段的间距(路径像素,亮段约占其 30%);固定物理尺度,长短线亮段一致。 */
45
+ flowPeriod?: number;
39
46
  pixelate: boolean;
40
47
  roundPixels: boolean;
41
48
  backgroundColor?: Hex8Color;
@@ -58,6 +65,8 @@ export declare class SceneTree extends MainLoop {
58
65
  protected _textRemeasureScheduled: boolean;
59
66
  protected _onFontLoad: () => void;
60
67
  protected _backgroundColor: Color;
68
+ protected _flowColor: Color;
69
+ protected _flowColorArray?: Float32Array;
61
70
  protected _previousViewport?: Viewport;
62
71
  protected _currentViewport?: Viewport;
63
72
  getPreviousViewport(): Viewport | undefined;
@@ -0,0 +1,16 @@
1
+ import { Material } from './Material';
2
+ /**
3
+ * FXAA 后处理材质:在「root FBO → 画布」的最终合成 draw 里顺带完成抗锯齿,
4
+ * 不新增渲染 pass、不占额外显存(对比 MSAA 的 4x multisample renderbuffer)。
5
+ *
6
+ * 实现为紧凑版 FXAA 3.11(5 次亮度探测 + 沿边缘方向 4 次采样混合):
7
+ * - 颜色在预乘 alpha 空间整体(rgba 一起)混合,保持预乘一致性;
8
+ * - 亮度加入小比例 alpha 项,暗色内容叠在透明背景上时边缘仍可被检出
9
+ * (纯预乘 rgb 的黑色与透明像素亮度同为 0,会漏检);
10
+ * - 平坦区域按对比度阈值早退、原样输出,避免文字/纹理内部被无谓软化。
11
+ */
12
+ export declare class FxaaMaterial extends Material {
13
+ protected static _instance: FxaaMaterial;
14
+ static get instance(): FxaaMaterial;
15
+ constructor();
16
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './EffectMaterial';
2
+ export * from './FxaaMaterial';
2
3
  export * from './Material';
3
4
  export * from './UvMaterial';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modern-canvas",
3
3
  "type": "module",
4
- "version": "0.26.2",
4
+ "version": "0.27.0",
5
5
  "packageManager": "pnpm@10.19.0",
6
6
  "description": "A JavaScript WebGL rendering engine. only the ESM.",
7
7
  "author": "wxm",
@@ -63,8 +63,8 @@
63
63
  "colord": "^2.9.3",
64
64
  "earcut": "^3.2.0",
65
65
  "modern-font": "^0.6.2",
66
- "modern-idoc": "^0.12.3",
67
- "modern-path2d": "^1.8.7",
66
+ "modern-idoc": "^0.12.4",
67
+ "modern-path2d": "^1.8.8",
68
68
  "modern-text": "^2.1.3"
69
69
  },
70
70
  "peerDependencies": {