@vectojs/core 0.2.5 → 0.2.7
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/{chunk-5KLB6BEZ.js → chunk-BWLNEJJW.js} +8 -8
- package/dist/{chunk-76NMTLYL.js → chunk-CTZQOM5Z.js} +1 -1
- package/dist/{chunk-TQ4H357Q.js → chunk-DWMQYHNC.js} +82 -13
- package/dist/{chunk-TPNADFNN.js → chunk-GTQRCY6W.js} +56 -26
- package/dist/{chunk-WEQRBXT2.mjs → chunk-HVJHXIKW.mjs} +54 -24
- package/dist/{chunk-SB3SCWLT.mjs → chunk-SSOP3F5F.mjs} +1 -1
- package/dist/{chunk-B3Z3JEJH.mjs → chunk-STWPTWO4.mjs} +1 -1
- package/dist/{chunk-P6MDWIEX.mjs → chunk-YVN3PJRC.mjs} +80 -11
- package/dist/components/SplineEntity.d.ts +5 -0
- package/dist/components/TextEntity.d.ts +6 -1
- package/dist/index.js +326 -134
- package/dist/index.mjs +217 -25
- package/dist/layout/LayoutWorkerSource.d.ts +1 -1
- package/dist/layout.js +3 -3
- package/dist/layout.mjs +2 -2
- package/dist/renderer/CanvasRenderer.d.ts +12 -1
- package/dist/renderer/IRenderer.d.ts +7 -0
- package/dist/renderer/url.d.ts +1 -1
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/text/MSDFTextEntity.d.ts +15 -1
- package/dist/text.js +3 -3
- package/dist/text.mjs +2 -2
- package/dist/tree/Entity.d.ts +31 -0
- package/dist/tree/Scene.d.ts +26 -3
- package/package.json +5 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LayoutWorkerManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-STWPTWO4.mjs";
|
|
4
4
|
|
|
5
5
|
// src/math/SpringPhysics.ts
|
|
6
|
+
var MAX_FRAME_DT = 0.25;
|
|
7
|
+
var MAX_STEP_DT = 1 / 120;
|
|
6
8
|
var SpringPhysics = class {
|
|
7
9
|
value;
|
|
8
10
|
target;
|
|
@@ -22,11 +24,22 @@ var SpringPhysics = class {
|
|
|
22
24
|
this.velocity = 0;
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
if (!(dt > 0)) return;
|
|
28
|
+
let remaining = dt < MAX_FRAME_DT ? dt : MAX_FRAME_DT;
|
|
29
|
+
while (remaining > 0) {
|
|
30
|
+
const step = remaining < MAX_STEP_DT ? remaining : MAX_STEP_DT;
|
|
31
|
+
const forceSpring = -this.stiffness * (this.value - this.target);
|
|
32
|
+
const forceDamping = -this.damping * this.velocity;
|
|
33
|
+
const acceleration = (forceSpring + forceDamping) / this.mass;
|
|
34
|
+
this.velocity += acceleration * step;
|
|
35
|
+
this.value += this.velocity * step;
|
|
36
|
+
remaining -= step;
|
|
37
|
+
if (this.isAtRest()) {
|
|
38
|
+
this.value = this.target;
|
|
39
|
+
this.velocity = 0;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
30
43
|
}
|
|
31
44
|
isAtRest() {
|
|
32
45
|
return Math.abs(this.value - this.target) < this.valEpsilon && Math.abs(this.velocity) < this.velEpsilon;
|
|
@@ -117,6 +130,14 @@ var SpringDriver = class {
|
|
|
117
130
|
};
|
|
118
131
|
|
|
119
132
|
// src/tree/Entity.ts
|
|
133
|
+
var ANIMATABLE_PROPS = /* @__PURE__ */ new Set([
|
|
134
|
+
"x",
|
|
135
|
+
"y",
|
|
136
|
+
"scaleX",
|
|
137
|
+
"scaleY",
|
|
138
|
+
"rotation",
|
|
139
|
+
"opacity"
|
|
140
|
+
]);
|
|
120
141
|
var VectoJSEvent = class {
|
|
121
142
|
/** The event name. */
|
|
122
143
|
type;
|
|
@@ -568,7 +589,12 @@ var Entity = class {
|
|
|
568
589
|
const end = anim.target[key];
|
|
569
590
|
if (typeof start === "number" && typeof end === "number") {
|
|
570
591
|
const easeOut = progress * (2 - progress);
|
|
571
|
-
|
|
592
|
+
const value = start + (end - start) * easeOut;
|
|
593
|
+
if (ANIMATABLE_PROPS.has(key)) {
|
|
594
|
+
this._applyAnimated(key, value);
|
|
595
|
+
} else {
|
|
596
|
+
this[key] = value;
|
|
597
|
+
}
|
|
572
598
|
}
|
|
573
599
|
}
|
|
574
600
|
if (progress >= 1) {
|
|
@@ -619,6 +645,10 @@ var Entity = class {
|
|
|
619
645
|
*/
|
|
620
646
|
destroy() {
|
|
621
647
|
this.animations = [];
|
|
648
|
+
for (const driver of this._drivers.values()) {
|
|
649
|
+
this._settleDriver(driver);
|
|
650
|
+
}
|
|
651
|
+
this._drivers.clear();
|
|
622
652
|
this.listeners.clear();
|
|
623
653
|
this.captureListeners.clear();
|
|
624
654
|
if (this.parent) {
|
|
@@ -862,6 +892,19 @@ var Entity = class {
|
|
|
862
892
|
getBatchRect() {
|
|
863
893
|
return null;
|
|
864
894
|
}
|
|
895
|
+
/**
|
|
896
|
+
* Opt into DOM content projection for entities that render static text.
|
|
897
|
+
* The {@link Scene} mirrors the returned text as a transparent DOM node
|
|
898
|
+
* positioned over the drawn glyphs, making canvas text findable (Ctrl+F),
|
|
899
|
+
* readable by screen readers and crawlers, translatable, and — when
|
|
900
|
+
* `selectable` is set — natively selectable. Returns `null` by default.
|
|
901
|
+
* Read on the a11y sync cadence, so text changes propagate automatically.
|
|
902
|
+
*
|
|
903
|
+
* @returns The projection descriptor, or `null` to project nothing.
|
|
904
|
+
*/
|
|
905
|
+
getContentProjection() {
|
|
906
|
+
return null;
|
|
907
|
+
}
|
|
865
908
|
/**
|
|
866
909
|
* Whether this entity still has a queued/running tween animation, or an
|
|
867
910
|
* active {@link setTransition}/{@link animateTo}/{@link springTo} property
|
|
@@ -989,6 +1032,8 @@ var MSDFTextEntity = class extends Entity {
|
|
|
989
1032
|
color;
|
|
990
1033
|
letterSpacing;
|
|
991
1034
|
lineHeight;
|
|
1035
|
+
maxWidth;
|
|
1036
|
+
maxHeight;
|
|
992
1037
|
text = "";
|
|
993
1038
|
lastRenderedSeqId = 0;
|
|
994
1039
|
rgbColorCache = /* @__PURE__ */ new Map();
|
|
@@ -1003,17 +1048,27 @@ var MSDFTextEntity = class extends Entity {
|
|
|
1003
1048
|
this.color = options.color ?? "#ffffff";
|
|
1004
1049
|
this.letterSpacing = options.letterSpacing ?? 0;
|
|
1005
1050
|
this.lineHeight = options.lineHeight;
|
|
1051
|
+
this.maxWidth = options.maxWidth ?? 1e3;
|
|
1052
|
+
this.maxHeight = options.maxHeight ?? 1e3;
|
|
1006
1053
|
this.setText(text);
|
|
1007
1054
|
}
|
|
1055
|
+
/** Change the wrap boundary and re-run layout for the current text. */
|
|
1056
|
+
setMaxWidth(maxWidth) {
|
|
1057
|
+
if (this.maxWidth === maxWidth) return;
|
|
1058
|
+
this.maxWidth = maxWidth;
|
|
1059
|
+
this.queueLayout();
|
|
1060
|
+
}
|
|
1008
1061
|
setText(text) {
|
|
1009
1062
|
if (this.text === text && this.layoutResult) return;
|
|
1010
1063
|
this.text = text;
|
|
1064
|
+
this.queueLayout();
|
|
1065
|
+
}
|
|
1066
|
+
queueLayout() {
|
|
1011
1067
|
LayoutWorkerManager.getInstance().queueLayout(this.id, this.text, {
|
|
1012
1068
|
fontId: this.font.id,
|
|
1013
1069
|
fontSize: this.fontSize,
|
|
1014
|
-
maxWidth:
|
|
1015
|
-
|
|
1016
|
-
maxHeight: 1e3,
|
|
1070
|
+
maxWidth: this.maxWidth,
|
|
1071
|
+
maxHeight: this.maxHeight,
|
|
1017
1072
|
fontData: this.font.data,
|
|
1018
1073
|
letterSpacing: this.letterSpacing,
|
|
1019
1074
|
lineHeight: this.lineHeight,
|
|
@@ -1025,6 +1080,18 @@ var MSDFTextEntity = class extends Entity {
|
|
|
1025
1080
|
}
|
|
1026
1081
|
});
|
|
1027
1082
|
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Mirror the rendered text into the DOM content layer: find-in-page, screen
|
|
1085
|
+
* readers, crawlers, and translation see the same string the canvas draws.
|
|
1086
|
+
*/
|
|
1087
|
+
getContentProjection() {
|
|
1088
|
+
if (!this.text) return null;
|
|
1089
|
+
return {
|
|
1090
|
+
text: this.text,
|
|
1091
|
+
font: `${this.fontSize}px ${this.fallbackFont}`,
|
|
1092
|
+
lineHeight: this.lineHeight
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1028
1095
|
isPointInside(globalX, globalY) {
|
|
1029
1096
|
if (!this.layoutResult) return false;
|
|
1030
1097
|
const local = this.worldToLocal(globalX, globalY);
|
|
@@ -1042,6 +1109,8 @@ var MSDFTextEntity = class extends Entity {
|
|
|
1042
1109
|
if (scene && scene.pointRenderer && scene.glCanvas && canUsePointGlyphs) {
|
|
1043
1110
|
scene.pointRenderer.setMSDFTexture(this.texture, this.font.distanceRange);
|
|
1044
1111
|
const worldRot = Math.atan2(world.b, world.a);
|
|
1112
|
+
let worldOpacity = this.opacity;
|
|
1113
|
+
for (let p = this.parent; p; p = p.parent) worldOpacity *= p.opacity;
|
|
1045
1114
|
const len2 = this.layoutResult.codePoints.length;
|
|
1046
1115
|
for (let i = 0; i < len2; i++) {
|
|
1047
1116
|
const code = this.layoutResult.codePoints[i];
|
|
@@ -1080,7 +1149,7 @@ var MSDFTextEntity = class extends Entity {
|
|
|
1080
1149
|
ab.right / aw,
|
|
1081
1150
|
v1,
|
|
1082
1151
|
runColor,
|
|
1083
|
-
|
|
1152
|
+
worldOpacity,
|
|
1084
1153
|
worldRot
|
|
1085
1154
|
);
|
|
1086
1155
|
}
|
|
@@ -96,6 +96,11 @@ export declare class SplineEntity extends Entity {
|
|
|
96
96
|
private bounds;
|
|
97
97
|
private offscreen;
|
|
98
98
|
private baked;
|
|
99
|
+
/** Logical (CSS-pixel) size of the baked bitmap — the blit destination size. */
|
|
100
|
+
private bakedWidth;
|
|
101
|
+
private bakedHeight;
|
|
102
|
+
/** Gradient strokes can't be baked to a solid-color bitmap; they render per-frame. */
|
|
103
|
+
private readonly containsGradient;
|
|
99
104
|
/** Lazily-flattened polylines (one Float32Array of [x,y,...] per segment) for hit-testing. */
|
|
100
105
|
private polylines;
|
|
101
106
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entity } from '../tree/Entity';
|
|
1
|
+
import { Entity, type ContentProjection } from '../tree/Entity';
|
|
2
2
|
import { IRenderer } from '../renderer/IRenderer';
|
|
3
3
|
export declare class TextEntity extends Entity {
|
|
4
4
|
text: string;
|
|
@@ -13,6 +13,11 @@ export declare class TextEntity extends Entity {
|
|
|
13
13
|
lineWidth: number;
|
|
14
14
|
private isHovered;
|
|
15
15
|
constructor(text: string, atlas: any, maxWidth: number, fontSize?: number);
|
|
16
|
+
/**
|
|
17
|
+
* Mirror the rendered text into the DOM content layer: find-in-page, screen
|
|
18
|
+
* readers, crawlers, and translation see the same string the canvas draws.
|
|
19
|
+
*/
|
|
20
|
+
getContentProjection(): ContentProjection | null;
|
|
16
21
|
/**
|
|
17
22
|
* Replace the text content. Runs the **cold** measurement pass (re-segment +
|
|
18
23
|
* re-measure) since the glyphs changed, then re-lays out.
|