@pixodesk/svg-animator-core 1.0.21 โ 1.0.22
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/README.md +127 -0
- package/dist/index.cjs +36 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7480 -1928
- package/dist/index.d.ts +7480 -1928
- package/dist/index.js +35 -4
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# animator-core
|
|
2
|
+
|
|
3
|
+
[](https://github.com/pixodesk/pixodesk-svg-animator/actions/workflows/ci.yml)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Platform-neutral core of the Pixodesk SVG animator: the document schema, the
|
|
7
|
+
effect materialisers, the interpolation engine and the path sampler โ with **no
|
|
8
|
+
DOM dependency at all**. It is what every player shares, so the web player and
|
|
9
|
+
the React Native player produce identical values from the same document.
|
|
10
|
+
|
|
11
|
+
# ๐ง **Status - This project is currently under development.**
|
|
12
|
+
|
|
13
|
+
## Do I need this package?
|
|
14
|
+
|
|
15
|
+
Usually **no**. If you just want to play an animation, install a player:
|
|
16
|
+
|
|
17
|
+
| You are building for | Install |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Browser (vanilla JS) | [`@pixodesk/svg-animator-web`](../svg-animator-web/README.md) |
|
|
20
|
+
| React | [`@pixodesk/svg-animator-react`](../svg-animator-react/README.md) |
|
|
21
|
+
| Vue | [`@pixodesk/svg-animator-vue`](../svg-animator-vue/README.md) |
|
|
22
|
+
| React Native | [`@pixodesk/svg-animator-rn`](../svg-animator-rn/README.md) ๐งช |
|
|
23
|
+
|
|
24
|
+
Each of those depends on this package and re-exports what you need.
|
|
25
|
+
|
|
26
|
+
Install it **directly** when you want to work with documents rather than play
|
|
27
|
+
them โ validating them, transforming them, flattening them for a renderer of
|
|
28
|
+
your own, or computing values at a given time without rendering anything.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @pixodesk/svg-animator-core
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Why it exists
|
|
35
|
+
|
|
36
|
+
A player has to answer two very different questions:
|
|
37
|
+
|
|
38
|
+
1. **What should be on screen at time _t_?** โ schema, effects, easing,
|
|
39
|
+
interpolation, path sampling. Pure computation, identical on every platform.
|
|
40
|
+
2. **How do I put it there?** โ DOM elements, WAAPI, `react-native-svg`.
|
|
41
|
+
Platform-specific.
|
|
42
|
+
|
|
43
|
+
Everything in category 1 lives here. The package compiles without the TypeScript
|
|
44
|
+
`dom` library, so a stray `document` reference is a build error rather than a
|
|
45
|
+
runtime crash on a non-browser platform.
|
|
46
|
+
|
|
47
|
+
## What's inside
|
|
48
|
+
|
|
49
|
+
| Area | Exports |
|
|
50
|
+
|---|---|
|
|
51
|
+
| **Schema & types** | `PxAnimatedSvgDocumentSchema`, `PxNodeSchema`, `PxEffectsSchema`, โฆ plus every `Px*` TypeScript type and the `px` schema builder |
|
|
52
|
+
| **Validation** | `isPxElementFileFormat`, `isPxElementFileFormatDeep`, `validateNodeEffects` |
|
|
53
|
+
| **Materialisers** | `materialiseAllInTree`, `applyPlayerEffects`, `materialiseInternalLoopsInTree`, `materialiseMotionPathsInTree`, `materialiseAnimatedUseInstances` |
|
|
54
|
+
| **Interpolation** | `calcAnimationValues`, `interpolateValue`, `getNormalisedBindings` |
|
|
55
|
+
| **Sampling / geometry** | `createPathSampler`, `evaluateMotionPathSegment`, bezier helpers, `cubicBezier`, `splitEasing` |
|
|
56
|
+
| **Text** | `materialiseGlyphText`, `layoutGlyphTextChars`, `extendedPathForBrowser` |
|
|
57
|
+
| **Node helpers** | `getNormalizedProps`, `sanitiseAttributeValue`, `resolveStyle`, `generateNewIds` |
|
|
58
|
+
| **Playback engine** | `createBasicFrameLoopAnimator` + the `PxPlatformAdapter` interface |
|
|
59
|
+
|
|
60
|
+
## The materialisation pipeline
|
|
61
|
+
|
|
62
|
+
`materialiseAllInTree(doc, engine)` is the single entry point that turns a
|
|
63
|
+
lightweight editor document into a flat tree any renderer can walk:
|
|
64
|
+
|
|
65
|
+
1. **Effects** โ `node.effects` (transformation, repeater, maskedBy, trimPath,
|
|
66
|
+
clone/retime, gradients, textPath) become real nodes, wrappers and defs.
|
|
67
|
+
2. **Loops** โ each property's `loop` is expanded into explicit keyframes.
|
|
68
|
+
3. **Motion paths** โ tangented `transform` keyframes plus `autoOrient` are
|
|
69
|
+
sampled into plain `{translate, rotate}` keyframes.
|
|
70
|
+
4. **Animated `<use>`** โ replaced by `<g>` + a deep clone with fresh ids.
|
|
71
|
+
|
|
72
|
+
Steps 3 and 4 run when `engine` is `webapi`. Pass `webapi` for **any renderer
|
|
73
|
+
without live `<use>` propagation** โ that includes `react-native-svg` โ and
|
|
74
|
+
`frames` only for the DOM, which resolves `<use>` references natively.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import {
|
|
78
|
+
materialiseAllInTree, generateNewIds, calcAnimationValues,
|
|
79
|
+
getNormalisedBindings, PxAnimatorEngine,
|
|
80
|
+
} from '@pixodesk/svg-animator-core';
|
|
81
|
+
|
|
82
|
+
// Flatten once โฆ
|
|
83
|
+
const flat = generateNewIds(materialiseAllInTree(doc, PxAnimatorEngine.webapi));
|
|
84
|
+
|
|
85
|
+
// โฆ then ask for values at any time, with no renderer involved.
|
|
86
|
+
for (const binding of getNormalisedBindings(flat, PxAnimatorEngine.frames) ?? []) {
|
|
87
|
+
const values = calcAnimationValues(binding.animate, 500); // t = 500 ms
|
|
88
|
+
console.log(binding.id, values); // โ { opacity: '0.5', transform: 'translate(โฆ)' }
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This is exactly how the React Native player precomputes its animation tracks, and
|
|
93
|
+
how the frames engine renders each tick in the browser โ same function, same
|
|
94
|
+
numbers.
|
|
95
|
+
|
|
96
|
+
## Writing your own player
|
|
97
|
+
|
|
98
|
+
Implement `PxPlatformAdapter` and hand it to `createBasicFrameLoopAnimator`; the
|
|
99
|
+
engine handles timing, delay, direction, iterations, fill, playback rate and the
|
|
100
|
+
lifecycle callbacks, then calls you with plain attribute writes.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { createBasicFrameLoopAnimator, type PxPlatformAdapter } from '@pixodesk/svg-animator-core';
|
|
104
|
+
|
|
105
|
+
const adapter: PxPlatformAdapter = {
|
|
106
|
+
isConnected: () => true,
|
|
107
|
+
setAttribute: (id, attrName, value) => { /* apply to your element */ },
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const api = createBasicFrameLoopAnimator(flatDoc, adapter, {
|
|
111
|
+
onFinish: () => console.log('done'),
|
|
112
|
+
});
|
|
113
|
+
api.play();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Frame scheduling resolves `requestAnimationFrame` from `globalThis` at call time
|
|
117
|
+
and falls back to `setTimeout`, so the engine works in browsers, React Native and
|
|
118
|
+
test environments with faked timers.
|
|
119
|
+
|
|
120
|
+
## Versioning
|
|
121
|
+
|
|
122
|
+
Every package in this repo is released in lockstep. A player depends on the
|
|
123
|
+
matching core version (`^x.y.z`), so upgrading a player upgrades the core with it.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
[MIT](../../LICENSE) ยฉ [Pixodesk](https://pixodesk.com)
|
package/dist/index.cjs
CHANGED
|
@@ -72,6 +72,7 @@ __export(index_exports, {
|
|
|
72
72
|
PxEffectsSchema: () => PxEffectsSchema,
|
|
73
73
|
PxElementAnimationSchema: () => PxElementAnimationSchema,
|
|
74
74
|
PxFillGradientEffectSchema: () => PxFillGradientEffectSchema,
|
|
75
|
+
PxGradientGeometryAnimationSchema: () => PxGradientGeometryAnimationSchema,
|
|
75
76
|
PxGradientSpreadMethod: () => PxGradientSpreadMethod,
|
|
76
77
|
PxGradientStopSchema: () => PxGradientStopSchema,
|
|
77
78
|
PxGradientType: () => PxGradientType,
|
|
@@ -725,6 +726,7 @@ var PxAnimatorConfigSchema = implementsInterface()(px.object({
|
|
|
725
726
|
resetOnFinish: px.boolean().optional(),
|
|
726
727
|
definitions: PxDefsSchema.optional(),
|
|
727
728
|
animate: px.record(PxElementAnimationSchema).optional(),
|
|
729
|
+
timeline: px.string().optional(),
|
|
728
730
|
debug: px.boolean().optional(),
|
|
729
731
|
debugInstName: px.string().optional()
|
|
730
732
|
}));
|
|
@@ -816,6 +818,17 @@ var PxAnimatableGradientStopsSchema = px.union([
|
|
|
816
818
|
px.object({ value: px.array(PxGradientStopSchema) }),
|
|
817
819
|
px.object({ keyframes: px.array(PxKeyframeSchema) })
|
|
818
820
|
]);
|
|
821
|
+
var PxGradientGeometryAnimationSchema = implementsInterface()(px.object({
|
|
822
|
+
gradientX1: PxPropertyAnimationSchema.optional(),
|
|
823
|
+
gradientY1: PxPropertyAnimationSchema.optional(),
|
|
824
|
+
gradientX2: PxPropertyAnimationSchema.optional(),
|
|
825
|
+
gradientY2: PxPropertyAnimationSchema.optional(),
|
|
826
|
+
gradientCx: PxPropertyAnimationSchema.optional(),
|
|
827
|
+
gradientCy: PxPropertyAnimationSchema.optional(),
|
|
828
|
+
gradientFx: PxPropertyAnimationSchema.optional(),
|
|
829
|
+
gradientFy: PxPropertyAnimationSchema.optional(),
|
|
830
|
+
gradientR: PxPropertyAnimationSchema.optional()
|
|
831
|
+
}));
|
|
819
832
|
var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
820
833
|
type: px.enum([PxGradientType.linear, PxGradientType.radial]),
|
|
821
834
|
p1: px.tuple([px.number(), px.number()]).optional(),
|
|
@@ -826,7 +839,8 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
|
826
839
|
stops: PxAnimatableGradientStopsSchema.optional(),
|
|
827
840
|
gradientUnits: px.string().optional(),
|
|
828
841
|
spreadMethod: px.string().optional(),
|
|
829
|
-
gradientTransform: px.string().optional()
|
|
842
|
+
gradientTransform: px.string().optional(),
|
|
843
|
+
animate: PxGradientGeometryAnimationSchema.optional()
|
|
830
844
|
}));
|
|
831
845
|
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
832
846
|
var PxTextPathEffectSchema = implementsInterface()(px.object({
|
|
@@ -2839,17 +2853,34 @@ function partsRecord(part, value, origin) {
|
|
|
2839
2853
|
return rec;
|
|
2840
2854
|
}
|
|
2841
2855
|
function readAnimatable(raw) {
|
|
2856
|
+
var _a, _b;
|
|
2842
2857
|
if (raw === void 0) return { kind: "absent" /* Absent */ };
|
|
2843
2858
|
if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
|
|
2844
2859
|
if (typeof raw === "object") {
|
|
2845
2860
|
const obj = raw;
|
|
2846
|
-
|
|
2847
|
-
|
|
2861
|
+
const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
|
|
2862
|
+
if (kfs) {
|
|
2863
|
+
return { kind: "animated" /* Animated */, keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
|
|
2848
2864
|
}
|
|
2849
|
-
|
|
2865
|
+
const staticValue = (_b = obj.value) != null ? _b : obj.v;
|
|
2866
|
+
if (staticValue !== void 0) return { kind: "static" /* Static */, value: staticValue };
|
|
2850
2867
|
}
|
|
2851
2868
|
return { kind: "static" /* Static */, value: raw };
|
|
2852
2869
|
}
|
|
2870
|
+
function normaliseKeyframe(kf) {
|
|
2871
|
+
if (!kf || typeof kf !== "object") return kf;
|
|
2872
|
+
const k = kf;
|
|
2873
|
+
if (k.t === void 0 && k.v === void 0 && k.e === void 0 && k.to === void 0 && k.ti === void 0) {
|
|
2874
|
+
return kf;
|
|
2875
|
+
}
|
|
2876
|
+
const out = __spreadValues({}, k);
|
|
2877
|
+
if (out.time === void 0 && k.t !== void 0) out.time = k.t;
|
|
2878
|
+
if (out.value === void 0 && k.v !== void 0) out.value = k.v;
|
|
2879
|
+
if (out.easing === void 0 && k.e !== void 0) out.easing = k.e;
|
|
2880
|
+
if (out.tangentOut === void 0 && k.to !== void 0) out.tangentOut = k.to;
|
|
2881
|
+
if (out.tangentIn === void 0 && k.ti !== void 0) out.tangentIn = k.ti;
|
|
2882
|
+
return out;
|
|
2883
|
+
}
|
|
2853
2884
|
function readStaticOrigin(raw, ctx) {
|
|
2854
2885
|
var _a;
|
|
2855
2886
|
const o = readAnimatable(raw);
|
|
@@ -5754,6 +5785,7 @@ function subtractMultiset(a, b) {
|
|
|
5754
5785
|
PxEffectsSchema,
|
|
5755
5786
|
PxElementAnimationSchema,
|
|
5756
5787
|
PxFillGradientEffectSchema,
|
|
5788
|
+
PxGradientGeometryAnimationSchema,
|
|
5757
5789
|
PxGradientSpreadMethod,
|
|
5758
5790
|
PxGradientStopSchema,
|
|
5759
5791
|
PxGradientType,
|