@voila.dev/motion 6.0.121 → 6.0.123
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 +4 -1
- package/dist/animate/js-animation.d.ts.map +1 -1
- package/dist/animate/js-animation.js +13 -11
- package/dist/animate/js-animation.js.map +2 -2
- package/dist/animate/style.d.ts +1 -1
- package/dist/animate/style.d.ts.map +1 -1
- package/dist/animate/style.js +18 -1
- package/dist/animate/style.js.map +2 -2
- package/dist/animate/types.d.ts +2 -2
- package/dist/animate/waapi.d.ts.map +1 -1
- package/dist/animate/waapi.js +5 -2
- package/dist/animate/waapi.js.map +2 -2
- package/dist/generators/spring.d.ts.map +1 -1
- package/dist/generators/spring.js +84 -36
- package/dist/generators/spring.js.map +3 -3
- package/dist/interpolate/color-parse.d.ts +1 -1
- package/dist/interpolate/color-parse.d.ts.map +1 -1
- package/dist/interpolate/color-parse.js +19 -1
- package/dist/interpolate/color-parse.js.map +2 -2
- package/dist/interpolate/mix.d.ts.map +1 -1
- package/dist/interpolate/mix.js.map +2 -2
- package/dist/sequence/sequence.d.ts.map +1 -1
- package/dist/sequence/sequence.js +32 -5
- package/dist/sequence/sequence.js.map +2 -2
- package/package.json +1 -1
- package/src/animate/js-animation.ts +15 -11
- package/src/animate/style.ts +28 -1
- package/src/animate/types.ts +2 -2
- package/src/animate/waapi.ts +7 -2
- package/src/generators/spring.ts +106 -40
- package/src/interpolate/color-parse.ts +31 -2
- package/src/interpolate/mix.ts +3 -2
- package/src/sequence/sequence.ts +61 -15
package/src/sequence/sequence.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { groupControls, thenable } from "#/animate/controls.ts";
|
|
2
|
+
import { planGenerator, totalDuration } from "#/animate/plan.ts";
|
|
2
3
|
import type {
|
|
3
4
|
AnimationControls,
|
|
4
5
|
AnimationOptions,
|
|
@@ -48,6 +49,36 @@ function startOf(
|
|
|
48
49
|
return labels.get(at) ?? cursor;
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* How long a segment that waits for an earlier one will run once launched.
|
|
54
|
+
* Its first keyframe is only read then, but a tween's length doesn't depend
|
|
55
|
+
* on it, and neither does a default spring's (its rest thresholds scale with
|
|
56
|
+
* the distance).
|
|
57
|
+
*/
|
|
58
|
+
function plannedDuration(keyframes: unknown, options: AnimationOptions) {
|
|
59
|
+
const channels =
|
|
60
|
+
typeof keyframes === "object" &&
|
|
61
|
+
keyframes !== null &&
|
|
62
|
+
!Array.isArray(keyframes)
|
|
63
|
+
? Object.values(keyframes)
|
|
64
|
+
: [keyframes];
|
|
65
|
+
const { delay } = options;
|
|
66
|
+
return (
|
|
67
|
+
(typeof delay === "number" ? delay : 0) +
|
|
68
|
+
Math.max(
|
|
69
|
+
0,
|
|
70
|
+
...channels.map((channel) => {
|
|
71
|
+
const frames = Array.isArray(channel) ? channel : [0, channel];
|
|
72
|
+
const { generator } = planGenerator(
|
|
73
|
+
frames.map((_frame, index) => index),
|
|
74
|
+
options,
|
|
75
|
+
);
|
|
76
|
+
return totalDuration(generator.duration, options);
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
51
82
|
/**
|
|
52
83
|
* Launches every segment at once, each delayed to its place on the
|
|
53
84
|
* timeline, so the whole sequence shares one clock and can be scrubbed. A
|
|
@@ -62,9 +93,13 @@ export function animateSequence(
|
|
|
62
93
|
): AnimationControls {
|
|
63
94
|
const begun = now();
|
|
64
95
|
const labels = new Map<string, number>();
|
|
65
|
-
const busy = new Map<
|
|
96
|
+
const busy = new Map<
|
|
97
|
+
object,
|
|
98
|
+
Map<string, { readonly finished: Promise<void>; readonly end: number }>
|
|
99
|
+
>();
|
|
66
100
|
const children: AnimationControls[] = [];
|
|
67
101
|
const waits: Promise<void>[] = [];
|
|
102
|
+
let end = 0;
|
|
68
103
|
let cursor = 0;
|
|
69
104
|
let previousStart = 0;
|
|
70
105
|
for (const segment of segments) {
|
|
@@ -78,7 +113,18 @@ export function animateSequence(
|
|
|
78
113
|
unknown,
|
|
79
114
|
SegmentOptions?,
|
|
80
115
|
];
|
|
81
|
-
const
|
|
116
|
+
const placed = startOf(own.at, cursor, previousStart, labels);
|
|
117
|
+
const keys =
|
|
118
|
+
typeof keyframes === "object" &&
|
|
119
|
+
keyframes !== null &&
|
|
120
|
+
!Array.isArray(keyframes)
|
|
121
|
+
? Object.keys(keyframes)
|
|
122
|
+
: ["value"];
|
|
123
|
+
const targets = resolveTargets(target);
|
|
124
|
+
const before = targets.flatMap((one) =>
|
|
125
|
+
keys.flatMap((key) => busy.get(one)?.get(key) ?? []),
|
|
126
|
+
);
|
|
127
|
+
const start = Math.max(placed, ...before.map((earlier) => earlier.end));
|
|
82
128
|
const { delay } = own;
|
|
83
129
|
/** Launched late, a segment only waits for what is left of its delay. */
|
|
84
130
|
function optionsAt(elapsed: number): AnimationOptions {
|
|
@@ -92,32 +138,28 @@ export function animateSequence(
|
|
|
92
138
|
: Math.max(0, offset + (delay ?? 0)),
|
|
93
139
|
};
|
|
94
140
|
}
|
|
95
|
-
const keys =
|
|
96
|
-
typeof keyframes === "object" &&
|
|
97
|
-
keyframes !== null &&
|
|
98
|
-
!Array.isArray(keyframes)
|
|
99
|
-
? Object.keys(keyframes)
|
|
100
|
-
: ["value"];
|
|
101
|
-
const targets = resolveTargets(target);
|
|
102
|
-
const before = targets.flatMap((one) =>
|
|
103
|
-
keys.flatMap((key) => busy.get(one)?.get(key) ?? []),
|
|
104
|
-
);
|
|
105
141
|
const launch = () =>
|
|
106
142
|
animateOne(target, keyframes, optionsAt((now() - begun) / 1000));
|
|
107
143
|
let finished: Promise<void>;
|
|
144
|
+
let ends: number;
|
|
108
145
|
if (before.length === 0) {
|
|
109
146
|
const controls = launch();
|
|
110
147
|
children.push(controls);
|
|
111
148
|
finished = controls.finished;
|
|
112
|
-
|
|
149
|
+
ends = Math.max(start, controls.duration);
|
|
113
150
|
} else {
|
|
114
|
-
finished = Promise.all(before
|
|
151
|
+
finished = Promise.all(before.map((earlier) => earlier.finished)).then(
|
|
152
|
+
() => launch().finished,
|
|
153
|
+
);
|
|
115
154
|
waits.push(finished);
|
|
155
|
+
ends = start + plannedDuration(keyframes, { ...options, ...own });
|
|
116
156
|
}
|
|
157
|
+
cursor = ends;
|
|
158
|
+
end = Math.max(end, ends);
|
|
117
159
|
for (const one of targets) {
|
|
118
160
|
const byKey = busy.get(one) ?? new Map();
|
|
119
161
|
busy.set(one, byKey);
|
|
120
|
-
for (const key of keys) byKey.set(key, finished);
|
|
162
|
+
for (const key of keys) byKey.set(key, { finished, end: ends });
|
|
121
163
|
}
|
|
122
164
|
previousStart = start;
|
|
123
165
|
}
|
|
@@ -125,5 +167,9 @@ export function animateSequence(
|
|
|
125
167
|
const finished = Promise.all([group.finished, ...waits]).then(
|
|
126
168
|
() => undefined,
|
|
127
169
|
);
|
|
170
|
+
// The segments still waiting count too: they end after the ones launched.
|
|
171
|
+
Object.defineProperty(group, "duration", {
|
|
172
|
+
value: Math.max(end, group.duration),
|
|
173
|
+
});
|
|
128
174
|
return Object.assign(group, thenable(finished));
|
|
129
175
|
}
|