animejs 4.4.1 → 4.5.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.
- package/README.md +2 -3
- package/dist/bundles/anime.esm.js +462 -213
- package/dist/bundles/anime.esm.min.js +2 -2
- package/dist/bundles/anime.umd.js +462 -213
- package/dist/bundles/anime.umd.min.js +2 -2
- package/dist/modules/adapters/index.cjs +14 -0
- package/dist/modules/adapters/index.d.ts +1 -0
- package/dist/modules/adapters/index.js +8 -0
- package/dist/modules/adapters/registry.cjs +149 -0
- package/dist/modules/adapters/registry.d.ts +65 -0
- package/dist/modules/adapters/registry.js +146 -0
- package/dist/modules/adapters/three/adapter.cjs +26 -0
- package/dist/modules/adapters/three/adapter.d.ts +15 -0
- package/dist/modules/adapters/three/adapter.js +24 -0
- package/dist/modules/adapters/three/helpers.cjs +297 -0
- package/dist/modules/adapters/three/helpers.d.ts +89 -0
- package/dist/modules/adapters/three/helpers.js +280 -0
- package/dist/modules/adapters/three/index.cjs +20 -0
- package/dist/modules/adapters/three/index.d.ts +2 -0
- package/dist/modules/adapters/three/index.js +12 -0
- package/dist/modules/adapters/three/instance.cjs +368 -0
- package/dist/modules/adapters/three/instance.d.ts +133 -0
- package/dist/modules/adapters/three/instance.js +365 -0
- package/dist/modules/adapters/three/object3d.cjs +214 -0
- package/dist/modules/adapters/three/object3d.d.ts +1 -0
- package/dist/modules/adapters/three/object3d.js +212 -0
- package/dist/modules/adapters/three/resolvers.cjs +105 -0
- package/dist/modules/adapters/three/resolvers.d.ts +1 -0
- package/dist/modules/adapters/three/resolvers.js +103 -0
- package/dist/modules/adapters/three/uniform.cjs +41 -0
- package/dist/modules/adapters/three/uniform.d.ts +1 -0
- package/dist/modules/adapters/three/uniform.js +39 -0
- package/dist/modules/animatable/animatable.cjs +2 -1
- package/dist/modules/animatable/animatable.d.ts +2 -1
- package/dist/modules/animatable/animatable.js +2 -1
- package/dist/modules/animatable/index.cjs +1 -1
- package/dist/modules/animatable/index.js +1 -1
- package/dist/modules/animation/additive.cjs +1 -1
- package/dist/modules/animation/additive.js +1 -1
- package/dist/modules/animation/animation.cjs +43 -16
- package/dist/modules/animation/animation.d.ts +5 -0
- package/dist/modules/animation/animation.js +45 -18
- package/dist/modules/animation/composition.cjs +38 -35
- package/dist/modules/animation/composition.js +38 -35
- package/dist/modules/animation/index.cjs +1 -1
- package/dist/modules/animation/index.js +1 -1
- package/dist/modules/core/clock.cjs +11 -15
- package/dist/modules/core/clock.d.ts +0 -2
- package/dist/modules/core/clock.js +11 -15
- package/dist/modules/core/colors.cjs +1 -1
- package/dist/modules/core/colors.js +1 -1
- package/dist/modules/core/consts.cjs +15 -1
- package/dist/modules/core/consts.d.ts +2 -0
- package/dist/modules/core/consts.js +14 -2
- package/dist/modules/core/globals.cjs +7 -4
- package/dist/modules/core/globals.d.ts +8 -2
- package/dist/modules/core/globals.js +8 -5
- package/dist/modules/core/helpers.cjs +2 -2
- package/dist/modules/core/helpers.js +3 -3
- package/dist/modules/core/render.cjs +64 -14
- package/dist/modules/core/render.js +65 -15
- package/dist/modules/core/styles.cjs +16 -2
- package/dist/modules/core/styles.js +16 -2
- package/dist/modules/core/targets.cjs +11 -13
- package/dist/modules/core/targets.js +11 -13
- package/dist/modules/core/transforms.cjs +1 -1
- package/dist/modules/core/transforms.js +1 -1
- package/dist/modules/core/units.cjs +1 -1
- package/dist/modules/core/units.js +1 -1
- package/dist/modules/core/values.cjs +73 -82
- package/dist/modules/core/values.d.ts +1 -2
- package/dist/modules/core/values.js +76 -84
- package/dist/modules/draggable/draggable.cjs +1 -1
- package/dist/modules/draggable/draggable.js +1 -1
- package/dist/modules/draggable/index.cjs +1 -1
- package/dist/modules/draggable/index.js +1 -1
- package/dist/modules/easings/cubic-bezier/index.cjs +1 -1
- package/dist/modules/easings/cubic-bezier/index.js +1 -1
- package/dist/modules/easings/eases/index.cjs +1 -1
- package/dist/modules/easings/eases/index.js +1 -1
- package/dist/modules/easings/eases/parser.cjs +3 -3
- package/dist/modules/easings/eases/parser.d.ts +4 -5
- package/dist/modules/easings/eases/parser.js +3 -3
- package/dist/modules/easings/index.cjs +1 -1
- package/dist/modules/easings/index.js +1 -1
- package/dist/modules/easings/irregular/index.cjs +1 -1
- package/dist/modules/easings/irregular/index.js +1 -1
- package/dist/modules/easings/linear/index.cjs +1 -1
- package/dist/modules/easings/linear/index.js +1 -1
- package/dist/modules/easings/none.cjs +1 -1
- package/dist/modules/easings/none.js +1 -1
- package/dist/modules/easings/spring/index.cjs +1 -1
- package/dist/modules/easings/spring/index.js +1 -1
- package/dist/modules/easings/steps/index.cjs +1 -1
- package/dist/modules/easings/steps/index.js +1 -1
- package/dist/modules/engine/engine.cjs +4 -2
- package/dist/modules/engine/engine.js +4 -2
- package/dist/modules/engine/index.cjs +1 -1
- package/dist/modules/engine/index.js +1 -1
- package/dist/modules/events/index.cjs +1 -1
- package/dist/modules/events/index.js +1 -1
- package/dist/modules/events/scroll.cjs +3 -1
- package/dist/modules/events/scroll.js +3 -1
- package/dist/modules/index.cjs +1 -1
- package/dist/modules/index.js +1 -1
- package/dist/modules/layout/index.cjs +1 -1
- package/dist/modules/layout/index.js +1 -1
- package/dist/modules/layout/layout.cjs +1 -1
- package/dist/modules/layout/layout.js +1 -1
- package/dist/modules/scope/index.cjs +1 -1
- package/dist/modules/scope/index.js +1 -1
- package/dist/modules/scope/scope.cjs +1 -1
- package/dist/modules/scope/scope.js +1 -1
- package/dist/modules/svg/drawable.cjs +1 -1
- package/dist/modules/svg/drawable.js +1 -1
- package/dist/modules/svg/helpers.cjs +1 -1
- package/dist/modules/svg/helpers.js +1 -1
- package/dist/modules/svg/index.cjs +1 -1
- package/dist/modules/svg/index.js +1 -1
- package/dist/modules/svg/morphto.cjs +1 -1
- package/dist/modules/svg/morphto.js +1 -1
- package/dist/modules/svg/motionpath.cjs +1 -1
- package/dist/modules/svg/motionpath.js +1 -1
- package/dist/modules/text/index.cjs +1 -1
- package/dist/modules/text/index.js +1 -1
- package/dist/modules/text/scramble.cjs +12 -2
- package/dist/modules/text/scramble.d.ts +9 -1
- package/dist/modules/text/scramble.js +12 -2
- package/dist/modules/text/split.cjs +2 -1
- package/dist/modules/text/split.js +2 -1
- package/dist/modules/timeline/index.cjs +1 -1
- package/dist/modules/timeline/index.js +1 -1
- package/dist/modules/timeline/position.cjs +1 -1
- package/dist/modules/timeline/position.js +1 -1
- package/dist/modules/timeline/timeline.cjs +14 -5
- package/dist/modules/timeline/timeline.d.ts +3 -3
- package/dist/modules/timeline/timeline.js +14 -5
- package/dist/modules/timer/index.cjs +1 -1
- package/dist/modules/timer/index.js +1 -1
- package/dist/modules/timer/timer.cjs +1 -1
- package/dist/modules/timer/timer.js +1 -1
- package/dist/modules/types/index.d.ts +36 -11
- package/dist/modules/utils/chainable.cjs +1 -1
- package/dist/modules/utils/chainable.js +1 -1
- package/dist/modules/utils/index.cjs +1 -1
- package/dist/modules/utils/index.js +1 -1
- package/dist/modules/utils/number.cjs +1 -1
- package/dist/modules/utils/number.js +1 -1
- package/dist/modules/utils/random.cjs +4 -3
- package/dist/modules/utils/random.d.ts +1 -1
- package/dist/modules/utils/random.js +4 -3
- package/dist/modules/utils/stagger.cjs +67 -13
- package/dist/modules/utils/stagger.js +69 -15
- package/dist/modules/utils/target.cjs +4 -1
- package/dist/modules/utils/target.js +4 -1
- package/dist/modules/utils/time.cjs +6 -5
- package/dist/modules/utils/time.d.ts +1 -1
- package/dist/modules/utils/time.js +6 -5
- package/dist/modules/waapi/composition.cjs +1 -1
- package/dist/modules/waapi/composition.js +1 -1
- package/dist/modules/waapi/index.cjs +1 -1
- package/dist/modules/waapi/index.js +1 -1
- package/dist/modules/waapi/waapi.cjs +1 -1
- package/dist/modules/waapi/waapi.js +1 -1
- package/package.json +38 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anime.js - UMD bundle
|
|
3
|
-
* @version v4.
|
|
3
|
+
* @version v4.5.0
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 - Julian Garnier
|
|
6
6
|
*/
|
|
@@ -39,6 +39,12 @@
|
|
|
39
39
|
/** @typedef {Timer&JSAnimation&Timeline} CallbackArgument */
|
|
40
40
|
/** @typedef {Animatable|Tickable|WAAPIAnimation|Draggable|ScrollObserver|TextSplitter|Scope|AutoLayout} Revertible */
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Object} TweakRegister
|
|
44
|
+
* @property {String} type
|
|
45
|
+
* @property {*} defaultValue
|
|
46
|
+
*/
|
|
47
|
+
|
|
42
48
|
// Stagger types
|
|
43
49
|
|
|
44
50
|
/**
|
|
@@ -58,11 +64,18 @@
|
|
|
58
64
|
* @property {Number|'first'|'center'|'last'|'random'|Array.<Number>} [from]
|
|
59
65
|
* @property {Boolean} [reversed]
|
|
60
66
|
* @property {Array.<Number>|Boolean} [grid]
|
|
61
|
-
* @property {('x'|'y')} [axis]
|
|
62
|
-
* @property {String|(
|
|
67
|
+
* @property {('x'|'y'|'z')} [axis]
|
|
68
|
+
* @property {String | { method(target: Target, i: Number, length: Number): Number }['method']} [use]
|
|
63
69
|
* @property {Number} [total]
|
|
64
70
|
* @property {EasingParam} [ease]
|
|
65
71
|
* @property {TweenModifier} [modifier]
|
|
72
|
+
* @property {Number|[Number, Number]} [jitter] Additive uniform noise on the
|
|
73
|
+
* computed stagger value. Number form gives flat `+/-jitter`; tuple form
|
|
74
|
+
* ramps the magnitude `start -> end` across the from/axis/grid ordering
|
|
75
|
+
* and respects `ease`.
|
|
76
|
+
* @property {Boolean|Number} [seed] Seed for jitter draws and `from: 'random'`
|
|
77
|
+
* shuffling. `false` (default) uses Math.random. `true` seeds with `0`. A
|
|
78
|
+
* number is used directly as the seed.
|
|
66
79
|
*/
|
|
67
80
|
|
|
68
81
|
// Targets types
|
|
@@ -138,10 +151,7 @@
|
|
|
138
151
|
|
|
139
152
|
/**
|
|
140
153
|
* @template T
|
|
141
|
-
* @
|
|
142
|
-
* @param {T} self - Returns itself
|
|
143
|
-
* @param {PointerEvent} [e]
|
|
144
|
-
* @return {*}
|
|
154
|
+
* @typedef {{ method(self: T): * }['method']} Callback
|
|
145
155
|
*/
|
|
146
156
|
|
|
147
157
|
/**
|
|
@@ -185,12 +195,17 @@
|
|
|
185
195
|
// Tween types
|
|
186
196
|
|
|
187
197
|
/**
|
|
198
|
+
* @typedef {Number|String|TweenKeyValue|EasingParam|Array.<Number|String|TweenKeyValue>} FunctionValueReturn
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @template [T=FunctionValueReturn]
|
|
188
203
|
* @callback FunctionValue
|
|
189
204
|
* @param {Target} [target] - The animated target
|
|
190
205
|
* @param {Number} [index] - The target index
|
|
191
206
|
* @param {TargetsArray} [targets] - The array of all animated targets
|
|
192
207
|
* @param {Tween|null} [prevTween] - The previous sibling tween for the same target and property
|
|
193
|
-
* @return {
|
|
208
|
+
* @return {T}
|
|
194
209
|
*/
|
|
195
210
|
|
|
196
211
|
/**
|
|
@@ -207,7 +222,7 @@
|
|
|
207
222
|
* @property {JSAnimation} parent
|
|
208
223
|
* @property {String} property
|
|
209
224
|
* @property {Target} target
|
|
210
|
-
* @property {String|Number} _value
|
|
225
|
+
* @property {String|Number|Object} _value
|
|
211
226
|
* @property {Function|null} _toFunc
|
|
212
227
|
* @property {Function|null} _fromFunc
|
|
213
228
|
* @property {EasingFunction} _ease
|
|
@@ -226,7 +241,11 @@
|
|
|
226
241
|
* @property {Number} _startTime
|
|
227
242
|
* @property {Number} _changeDuration
|
|
228
243
|
* @property {Number} _absoluteStartTime
|
|
244
|
+
* @property {Number} _absoluteUpdateStartTime
|
|
245
|
+
* @property {Number} _absoluteEndTime
|
|
246
|
+
* @property {Number} _hasFromValue
|
|
229
247
|
* @property {tweenTypes} _tweenType
|
|
248
|
+
* @property {((target: any, value: number, tween: Tween) => void) | null} _setter
|
|
230
249
|
* @property {valueTypes} _valueType
|
|
231
250
|
* @property {Number} _composition
|
|
232
251
|
* @property {Number} _isOverlapped
|
|
@@ -247,8 +266,8 @@
|
|
|
247
266
|
* @property {Number} n - Single number value
|
|
248
267
|
* @property {String} u - Value unit
|
|
249
268
|
* @property {String} o - Value operator
|
|
250
|
-
* @property {Array.<Number>} d - Array of Numbers (
|
|
251
|
-
* @property {Array.<String>} s - Strings (
|
|
269
|
+
* @property {Array.<Number>} d - Array of Numbers (complex / color value type)
|
|
270
|
+
* @property {Array.<String>} s - Strings (complex value type)
|
|
252
271
|
*/
|
|
253
272
|
|
|
254
273
|
/** @typedef {{_head: null|Tween, _tail: null|Tween}} TweenPropertySiblings */
|
|
@@ -259,7 +278,7 @@
|
|
|
259
278
|
// JSAnimation types
|
|
260
279
|
|
|
261
280
|
/**
|
|
262
|
-
* @typedef {Number|String|FunctionValue|EasingParam} TweenParamValue
|
|
281
|
+
* @typedef {Number|String|FunctionValue|EasingParam|TweakRegister} TweenParamValue
|
|
263
282
|
*/
|
|
264
283
|
|
|
265
284
|
/**
|
|
@@ -452,7 +471,7 @@
|
|
|
452
471
|
*/
|
|
453
472
|
|
|
454
473
|
/**
|
|
455
|
-
* @typedef {Record<String, TweenParamValue | EasingParam | TweenModifier | TweenComposition | AnimatablePropertyParamsOptions> &
|
|
474
|
+
* @typedef {Record<String, TweenParamValue | EasingParam | TweenModifier | TweenComposition | AnimatablePropertyParamsOptions | Callback<JSAnimation>> & AnimatablePropertyParamsOptions & TickableCallbacks<JSAnimation> & RenderableCallbacks<JSAnimation>} AnimatableParams
|
|
456
475
|
*/
|
|
457
476
|
|
|
458
477
|
// Scope types
|
|
@@ -495,7 +514,7 @@
|
|
|
495
514
|
/**
|
|
496
515
|
* @callback ScopeMethod
|
|
497
516
|
* @param {...*} args
|
|
498
|
-
* @return {
|
|
517
|
+
* @return {*}
|
|
499
518
|
*/
|
|
500
519
|
|
|
501
520
|
// Scroll types
|
|
@@ -731,6 +750,11 @@
|
|
|
731
750
|
const emptyString = '';
|
|
732
751
|
const cssVarPrefix = 'var(';
|
|
733
752
|
|
|
753
|
+
// Arrays
|
|
754
|
+
|
|
755
|
+
// Shared sentinel for tween slots that don't hold array data. Never mutated, only read; COMPLEX and COLOR tweens always replace the slot before writing.
|
|
756
|
+
const emptyArray = [];
|
|
757
|
+
|
|
734
758
|
const shortTransforms = /*#__PURE__*/ (() => {
|
|
735
759
|
const map = new Map();
|
|
736
760
|
map.set('x', 'translateX');
|
|
@@ -764,6 +788,13 @@
|
|
|
764
788
|
/** @return {void} */
|
|
765
789
|
const noop = () => {};
|
|
766
790
|
|
|
791
|
+
/**
|
|
792
|
+
* @template T
|
|
793
|
+
* @param {T} v
|
|
794
|
+
* @return {T}
|
|
795
|
+
*/
|
|
796
|
+
const noopModifier = v => v;
|
|
797
|
+
|
|
767
798
|
// Regex
|
|
768
799
|
|
|
769
800
|
const validRgbHslRgx = /\)\s*[-.\d]/;
|
|
@@ -785,10 +816,13 @@
|
|
|
785
816
|
/**
|
|
786
817
|
* @typedef {Object} EditorGlobals
|
|
787
818
|
* @property {boolean} showPanel
|
|
788
|
-
* @property {boolean} synced
|
|
789
819
|
* @property {Function} addAnimation
|
|
820
|
+
* @property {Function} addSet
|
|
790
821
|
* @property {Function} addTimeline
|
|
791
822
|
* @property {Function} addTimelineChild
|
|
823
|
+
* @property {Function} addTimelineLabel
|
|
824
|
+
* @property {Function} addTimelineCall
|
|
825
|
+
* @property {Function} addTimelineSync
|
|
792
826
|
* @property {Function} resolveStagger
|
|
793
827
|
* @property {Object|null} _head
|
|
794
828
|
* @property {Object|null} _tail
|
|
@@ -811,7 +845,7 @@
|
|
|
811
845
|
loopDelay: 0,
|
|
812
846
|
ease: 'out(2)',
|
|
813
847
|
composition: compositionTypes.replace,
|
|
814
|
-
modifier:
|
|
848
|
+
modifier: noopModifier,
|
|
815
849
|
onBegin: noop,
|
|
816
850
|
onBeforeUpdate: noop,
|
|
817
851
|
onUpdate: noop,
|
|
@@ -841,7 +875,7 @@
|
|
|
841
875
|
editor: null,
|
|
842
876
|
};
|
|
843
877
|
|
|
844
|
-
const globalVersions = { version: '4.
|
|
878
|
+
const globalVersions = { version: '4.5.0', engine: null };
|
|
845
879
|
|
|
846
880
|
if (isBrowser) {
|
|
847
881
|
if (!win.AnimeJS) win.AnimeJS = [];
|
|
@@ -988,7 +1022,7 @@
|
|
|
988
1022
|
* @param {Number} factor - Interpolation factor in the range [0, 1]
|
|
989
1023
|
* @return {Number} The interpolated value
|
|
990
1024
|
*/
|
|
991
|
-
const lerp$1 = (start, end, factor) => start + (end - start) * factor;
|
|
1025
|
+
const lerp$1 = (start, end, factor) => factor === 1 ? end : factor === 0 ? start : start + (end - start) * factor;
|
|
992
1026
|
|
|
993
1027
|
/**
|
|
994
1028
|
* Replaces infinity with maximum safe value
|
|
@@ -1237,6 +1271,61 @@
|
|
|
1237
1271
|
return str;
|
|
1238
1272
|
};
|
|
1239
1273
|
|
|
1274
|
+
/**
|
|
1275
|
+
* Anime.js adapter API. Each library or class group that wants to extend `animate()` and `utils.set()` calls `registerAdapter()` to create its own `Adapter`. The returned `Adapter` exposes `registerTargetAdapter(detect)` for per-class detection and `registerPropertyResolver(fn)` for global Color / Vector / pattern-based fallbacks.
|
|
1276
|
+
*
|
|
1277
|
+
* import { registerAdapter } from 'animejs/adapters';
|
|
1278
|
+
*
|
|
1279
|
+
* const myAdapter = registerAdapter();
|
|
1280
|
+
* const widget = myAdapter.registerTargetAdapter((t) => t instanceof MyWidget);
|
|
1281
|
+
* widget.registerProperty('value',
|
|
1282
|
+
* (t) => t.getValue(),
|
|
1283
|
+
* (target, value) => target.setValue(value),
|
|
1284
|
+
* );
|
|
1285
|
+
*
|
|
1286
|
+
* For scalar tweens, `value` is the interpolated number. For color and complex tweens it is `undefined`; read `tween._numbers` instead. `gate(target)` scopes the prop to a subset of matching targets.
|
|
1287
|
+
*
|
|
1288
|
+
* Resolution order: every Adapter's target adapters in registration order (first match wins) then every Adapter's property resolvers (first non-null wins) then engine direct property path.
|
|
1289
|
+
*/
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
const adapters = /** @type {Adapter[]} */([]);
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Internal resolution. Tries every Adapter's target adapters first (in registration order, first match wins), then every Adapter's property resolvers.
|
|
1296
|
+
*
|
|
1297
|
+
* @param {any} target
|
|
1298
|
+
* @param {string} name
|
|
1299
|
+
* @return {TargetAdapterEntry | null}
|
|
1300
|
+
*/
|
|
1301
|
+
function resolveAdapterEntry(target, name) {
|
|
1302
|
+
if (!target) return null;
|
|
1303
|
+
const al = adapters.length;
|
|
1304
|
+
outer: for (let i = 0; i < al; i++) {
|
|
1305
|
+
const a = adapters[i];
|
|
1306
|
+
if (a.detect && !a.detect(target)) continue;
|
|
1307
|
+
const tas = a.targetAdapters;
|
|
1308
|
+
for (let j = 0, m = tas.length; j < m; j++) {
|
|
1309
|
+
const ta = tas[j];
|
|
1310
|
+
if (ta.detect(target)) {
|
|
1311
|
+
const entry = ta.props[name];
|
|
1312
|
+
if (entry && (!entry.gate || entry.gate(target))) return entry;
|
|
1313
|
+
break outer;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
for (let i = 0; i < al; i++) {
|
|
1318
|
+
const a = adapters[i];
|
|
1319
|
+
if (a.detect && !a.detect(target)) continue;
|
|
1320
|
+
const rs = a.propertyResolvers;
|
|
1321
|
+
for (let j = 0, m = rs.length; j < m; j++) {
|
|
1322
|
+
const entry = rs[j](target, name);
|
|
1323
|
+
if (entry) return entry;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return null;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1240
1329
|
|
|
1241
1330
|
|
|
1242
1331
|
/**
|
|
@@ -1334,6 +1423,21 @@
|
|
|
1334
1423
|
return isUnd(targetValue) ? defaultValue : targetValue;
|
|
1335
1424
|
};
|
|
1336
1425
|
|
|
1426
|
+
/**
|
|
1427
|
+
* Resolve against the target when it's a DOM element, otherwise fall back to :root so non-DOM targets like three.js meshes and custom adapters still pick up CSS variables defined on the document.
|
|
1428
|
+
*
|
|
1429
|
+
* @param {String} value
|
|
1430
|
+
* @param {Target} target
|
|
1431
|
+
* @return {String|Number}
|
|
1432
|
+
*/
|
|
1433
|
+
const resolveCssVar = (value, target) => {
|
|
1434
|
+
const match = value.match(cssVariableMatchRgx);
|
|
1435
|
+
const el = target[isDomSymbol] ? target : document.documentElement;
|
|
1436
|
+
let computed = getComputedStyle(/** @type {HTMLElement} */(el))?.getPropertyValue(match[1]);
|
|
1437
|
+
if ((!computed || computed.trim() === emptyString) && match[2]) computed = match[2].trim();
|
|
1438
|
+
return computed || 0;
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1337
1441
|
/**
|
|
1338
1442
|
* @param {TweenPropValue} value
|
|
1339
1443
|
* @param {Target} target
|
|
@@ -1344,30 +1448,26 @@
|
|
|
1344
1448
|
* @return {any}
|
|
1345
1449
|
*/
|
|
1346
1450
|
const getFunctionValue = (value, target, index, targets, store, prevTween) => {
|
|
1347
|
-
let func;
|
|
1348
1451
|
if (isFnc(value)) {
|
|
1349
|
-
|
|
1452
|
+
if (!store) {
|
|
1453
|
+
const computed = /** @type {Function} */(value)(target, index, targets, prevTween);
|
|
1454
|
+
// Fallback to 0 if the function returns undefined, NaN, null, false or 0
|
|
1455
|
+
return !isNaN(+computed) ? +computed : computed || 0;
|
|
1456
|
+
}
|
|
1457
|
+
const func = () => {
|
|
1350
1458
|
const computed = /** @type {Function} */(value)(target, index, targets, prevTween);
|
|
1351
|
-
// Fallback to 0 if the function returns undefined / NaN / null / false / 0
|
|
1352
1459
|
return !isNaN(+computed) ? +computed : computed || 0;
|
|
1353
1460
|
};
|
|
1354
|
-
|
|
1355
|
-
func
|
|
1356
|
-
const match = value.match(cssVariableMatchRgx);
|
|
1357
|
-
const cssVarName = match[1];
|
|
1358
|
-
const fallbackValue = match[2];
|
|
1359
|
-
let computed = getComputedStyle(/** @type {HTMLElement} */(target))?.getPropertyValue(cssVarName);
|
|
1360
|
-
// Use fallback if CSS variable is not set or empty
|
|
1361
|
-
if ((!computed || computed.trim() === emptyString) && fallbackValue) {
|
|
1362
|
-
computed = fallbackValue.trim();
|
|
1363
|
-
}
|
|
1364
|
-
return computed || 0;
|
|
1365
|
-
};
|
|
1366
|
-
} else {
|
|
1367
|
-
return value;
|
|
1461
|
+
store.func = func;
|
|
1462
|
+
return func();
|
|
1368
1463
|
}
|
|
1369
|
-
if (
|
|
1370
|
-
|
|
1464
|
+
if (isStr(value) && stringStartsWith(value, cssVarPrefix)) {
|
|
1465
|
+
if (!store) return resolveCssVar(/** @type {String} */(value), target);
|
|
1466
|
+
const func = () => resolveCssVar(/** @type {String} */(value), target);
|
|
1467
|
+
store.func = func;
|
|
1468
|
+
return func();
|
|
1469
|
+
}
|
|
1470
|
+
return value;
|
|
1371
1471
|
};
|
|
1372
1472
|
|
|
1373
1473
|
/**
|
|
@@ -1414,6 +1514,12 @@
|
|
|
1414
1514
|
*/
|
|
1415
1515
|
const getOriginalAnimatableValue = (target, propName, tweenType, animationInlineStyles) => {
|
|
1416
1516
|
const type = !isUnd(tweenType) ? tweenType : getTweenType(target, propName);
|
|
1517
|
+
const adapterProp = resolveAdapterEntry(target, propName);
|
|
1518
|
+
if (adapterProp) {
|
|
1519
|
+
const value = adapterProp.get(target);
|
|
1520
|
+
if (value && animationInlineStyles) animationInlineStyles[propName] = value;
|
|
1521
|
+
return value == null ? 0 : value;
|
|
1522
|
+
}
|
|
1417
1523
|
if (type === tweenTypes.OBJECT) {
|
|
1418
1524
|
const value = target[propName];
|
|
1419
1525
|
if (value && animationInlineStyles) animationInlineStyles[propName] = value;
|
|
@@ -1455,7 +1561,7 @@
|
|
|
1455
1561
|
};
|
|
1456
1562
|
|
|
1457
1563
|
/**
|
|
1458
|
-
* @param {String|Number} rawValue
|
|
1564
|
+
* @param {String|Number|Object} rawValue
|
|
1459
1565
|
* @param {TweenDecomposedValue} targetObject
|
|
1460
1566
|
* @return {TweenDecomposedValue}
|
|
1461
1567
|
*/
|
|
@@ -1473,39 +1579,38 @@
|
|
|
1473
1579
|
// It's a number
|
|
1474
1580
|
targetObject.n = num;
|
|
1475
1581
|
return targetObject;
|
|
1582
|
+
}
|
|
1583
|
+
// let str = /** @type {String} */(rawValue).trim();
|
|
1584
|
+
let str = /** @type {String} */(rawValue);
|
|
1585
|
+
// Parsing operators (+=, -=, *=) manually is much faster than using regex here
|
|
1586
|
+
if (str[1] === '=') {
|
|
1587
|
+
targetObject.o = str[0];
|
|
1588
|
+
str = str.slice(2);
|
|
1589
|
+
}
|
|
1590
|
+
// Skip exec regex if the value type is complex or color to avoid long regex backtracking
|
|
1591
|
+
const unitMatch = str.includes(' ') ? false : unitsExecRgx.exec(str);
|
|
1592
|
+
if (unitMatch) {
|
|
1593
|
+
// Has a number and a unit
|
|
1594
|
+
targetObject.t = valueTypes.UNIT;
|
|
1595
|
+
targetObject.n = +unitMatch[1];
|
|
1596
|
+
targetObject.u = unitMatch[2];
|
|
1597
|
+
return targetObject;
|
|
1598
|
+
} else if (targetObject.o) {
|
|
1599
|
+
// Has an operator (+=, -=, *=)
|
|
1600
|
+
targetObject.n = +str;
|
|
1601
|
+
return targetObject;
|
|
1602
|
+
} else if (isCol(str)) {
|
|
1603
|
+
// Color string
|
|
1604
|
+
targetObject.t = valueTypes.COLOR;
|
|
1605
|
+
targetObject.d = convertColorStringValuesToRgbaArray(str);
|
|
1606
|
+
return targetObject;
|
|
1476
1607
|
} else {
|
|
1477
|
-
//
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
}
|
|
1484
|
-
// Skip exec regex if the value type is complex or color to avoid long regex backtracking
|
|
1485
|
-
const unitMatch = str.includes(' ') ? false : unitsExecRgx.exec(str);
|
|
1486
|
-
if (unitMatch) {
|
|
1487
|
-
// Has a number and a unit
|
|
1488
|
-
targetObject.t = valueTypes.UNIT;
|
|
1489
|
-
targetObject.n = +unitMatch[1];
|
|
1490
|
-
targetObject.u = unitMatch[2];
|
|
1491
|
-
return targetObject;
|
|
1492
|
-
} else if (targetObject.o) {
|
|
1493
|
-
// Has an operator (+=, -=, *=)
|
|
1494
|
-
targetObject.n = +str;
|
|
1495
|
-
return targetObject;
|
|
1496
|
-
} else if (isCol(str)) {
|
|
1497
|
-
// Is a color
|
|
1498
|
-
targetObject.t = valueTypes.COLOR;
|
|
1499
|
-
targetObject.d = convertColorStringValuesToRgbaArray(str);
|
|
1500
|
-
return targetObject;
|
|
1501
|
-
} else {
|
|
1502
|
-
// Is a more complex string (generally svg coords, calc() or filters CSS values)
|
|
1503
|
-
const matchedNumbers = str.match(digitWithExponentRgx);
|
|
1504
|
-
targetObject.t = valueTypes.COMPLEX;
|
|
1505
|
-
targetObject.d = matchedNumbers ? matchedNumbers.map(Number) : [];
|
|
1506
|
-
targetObject.s = str.split(digitWithExponentRgx) || [];
|
|
1507
|
-
return targetObject;
|
|
1508
|
-
}
|
|
1608
|
+
// Is a more complex string (generally svg coords, calc() or filters CSS values)
|
|
1609
|
+
const matchedNumbers = str.match(digitWithExponentRgx);
|
|
1610
|
+
targetObject.t = valueTypes.COMPLEX;
|
|
1611
|
+
targetObject.d = matchedNumbers ? matchedNumbers.map(Number) : [];
|
|
1612
|
+
targetObject.s = str.split(digitWithExponentRgx) || [];
|
|
1613
|
+
return targetObject;
|
|
1509
1614
|
}
|
|
1510
1615
|
};
|
|
1511
1616
|
|
|
@@ -1526,30 +1631,6 @@
|
|
|
1526
1631
|
|
|
1527
1632
|
const decomposedOriginalValue = createDecomposedValueTargetObject();
|
|
1528
1633
|
|
|
1529
|
-
/**
|
|
1530
|
-
* @param {Tween} tween
|
|
1531
|
-
* @param {Number} progress
|
|
1532
|
-
* @param {Number} precision
|
|
1533
|
-
* @return {String}
|
|
1534
|
-
*/
|
|
1535
|
-
const composeColorValue = (tween, progress, precision) => {
|
|
1536
|
-
const mod = tween._modifier;
|
|
1537
|
-
const fn = tween._fromNumbers;
|
|
1538
|
-
const tn = tween._toNumbers;
|
|
1539
|
-
const r = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[0], tn[0], progress))), 0, 255), 0);
|
|
1540
|
-
const g = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[1], tn[1], progress))), 0, 255), 0);
|
|
1541
|
-
const b = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[2], tn[2], progress))), 0, 255), 0);
|
|
1542
|
-
const a = clamp$1(/** @type {Number} */(mod(round$1(lerp$1(fn[3], tn[3], progress), precision))), 0, 1);
|
|
1543
|
-
if (tween._composition !== compositionTypes.none) {
|
|
1544
|
-
const ns = tween._numbers;
|
|
1545
|
-
ns[0] = r;
|
|
1546
|
-
ns[1] = g;
|
|
1547
|
-
ns[2] = b;
|
|
1548
|
-
ns[3] = a;
|
|
1549
|
-
}
|
|
1550
|
-
return `rgba(${r},${g},${b},${a})`;
|
|
1551
|
-
};
|
|
1552
|
-
|
|
1553
1634
|
/**
|
|
1554
1635
|
* @param {Tween} tween
|
|
1555
1636
|
* @param {Number} progress
|
|
@@ -1561,15 +1642,14 @@
|
|
|
1561
1642
|
const fn = tween._fromNumbers;
|
|
1562
1643
|
const tn = tween._toNumbers;
|
|
1563
1644
|
const ts = tween._strings;
|
|
1564
|
-
const hasComposition = tween._composition !== compositionTypes.none;
|
|
1565
1645
|
let v = ts[0];
|
|
1566
1646
|
for (let j = 0, l = tn.length; j < l; j++) {
|
|
1567
1647
|
const n = /** @type {Number} */(mod(round$1(lerp$1(fn[j], tn[j], progress), precision)));
|
|
1568
1648
|
const s = ts[j + 1];
|
|
1569
1649
|
v += `${s ? n + s : n}`;
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1650
|
+
// Keep _numbers fresh for every tween, not only composed ones, so a non-composition setter that reads the lerped triplet such as three transformOrigin still animates.
|
|
1651
|
+
// Potential optimization, skip the write when nothing reads it: if (hasComposition || tween._setter) tween._numbers[j] = n;
|
|
1652
|
+
tween._numbers[j] = n;
|
|
1573
1653
|
}
|
|
1574
1654
|
return v;
|
|
1575
1655
|
};
|
|
@@ -1621,12 +1701,14 @@
|
|
|
1621
1701
|
// Execute the "expensive" iterations calculations only when necessary
|
|
1622
1702
|
if (iterationCount > 1) {
|
|
1623
1703
|
// bitwise NOT operator seems to be generally faster than Math.floor() across browsers
|
|
1624
|
-
const
|
|
1704
|
+
const period = iterationDuration + (isCurrentTimeEqualOrAboveDuration ? 0 : _loopDelay);
|
|
1705
|
+
const currentIteration = ~~(tickableCurrentTime / period);
|
|
1625
1706
|
tickable._currentIteration = clamp$1(currentIteration, 0, iterationCount);
|
|
1626
1707
|
// Prevent the iteration count to go above the max iterations when reaching the end of the animation
|
|
1627
1708
|
if (isCurrentTimeEqualOrAboveDuration) tickable._currentIteration--;
|
|
1628
1709
|
isOdd = tickable._currentIteration % 2;
|
|
1629
|
-
|
|
1710
|
+
// Derive elapsed from the same `~~` truncation that gave currentIteration. Using `% period` here can disagree with `~~(/period)` under float drift at iteration boundaries and write the wrong end of the tween for one frame.
|
|
1711
|
+
iterationElapsedTime = tickableCurrentTime - currentIteration * period || 0;
|
|
1630
1712
|
}
|
|
1631
1713
|
|
|
1632
1714
|
// Checks if exactly one of _reversed and (_alternate && isOdd) is true
|
|
@@ -1658,12 +1740,14 @@
|
|
|
1658
1740
|
if (
|
|
1659
1741
|
forcedTick ||
|
|
1660
1742
|
tickMode === tickModes.AUTO && (
|
|
1661
|
-
|
|
1743
|
+
// Timeline children render from their offset instead of their delay so the gap left by a truncated sibling is covered on seek.
|
|
1744
|
+
time >= (parent && tickableDelay > 0 ? 0 : tickableDelay) && time <= tickableEndTime || // Normal render
|
|
1662
1745
|
time <= tickableDelay && tickablePrevTime > tickableDelay || // Playhead is before the animation start time so make sure the animation is at its initial state
|
|
1663
1746
|
time >= tickableEndTime && tickablePrevTime !== duration // Playhead is after the animation end time so make sure the animation is at its end state
|
|
1664
1747
|
) ||
|
|
1665
1748
|
iterationTime >= tickableEndTime && tickablePrevTime !== duration ||
|
|
1666
|
-
iterationTime
|
|
1749
|
+
// iterationTime is per-iteration, compared to the delay to catch a backward seek into a looped iteration's delay region. Exclude the final settled end, where iterationTime clamps to duration and would falsely match the delay region when the delay exceeds the duration.
|
|
1750
|
+
iterationTime <= tickableDelay && tickablePrevTime > 0 && !isCurrentTimeEqualOrAboveDuration ||
|
|
1667
1751
|
time <= tickablePrevTime && tickablePrevTime === duration && completed || // Force a render if a seek occurs on an completed animation
|
|
1668
1752
|
isCurrentTimeEqualOrAboveDuration && !completed && isSetter // This prevents 0 duration tickables to be skipped
|
|
1669
1753
|
) {
|
|
@@ -1679,7 +1763,8 @@
|
|
|
1679
1763
|
|
|
1680
1764
|
// Time has jumped more than globals.tickThreshold so consider this tick manual
|
|
1681
1765
|
const forcedRender = forcedTick || (isRunningBackwards ? deltaTime * -1 : deltaTime) >= globals.tickThreshold;
|
|
1682
|
-
|
|
1766
|
+
// Round to match the precision of tween._absoluteStartTime so equal-time boundary checks compare cleanly without floating point drift from the unrounded _offset.
|
|
1767
|
+
const absoluteTime = round$1(tickable._offset + (parent ? parent._offset : 0) + tickableDelay + iterationTime, 12);
|
|
1683
1768
|
|
|
1684
1769
|
// Only Animation can have tweens, Timer returns undefined
|
|
1685
1770
|
let tween = /** @type {Tween} */(/** @type {JSAnimation} */(tickable)._head);
|
|
@@ -1698,15 +1783,38 @@
|
|
|
1698
1783
|
const tweenNextRep = tween._nextRep;
|
|
1699
1784
|
const tweenPrevRep = tween._prevRep;
|
|
1700
1785
|
const tweenHasComposition = tweenComposition !== compositionTypes.none;
|
|
1786
|
+
// The previous sibling stops writing at its truncated end, so this tween takes over the hold from that point.
|
|
1787
|
+
const tweenPrevRepEndTime = tweenPrevRep ? tweenPrevRep._absoluteStartTime + tweenPrevRep._changeDuration : 0;
|
|
1788
|
+
const tweenPrevRepIsCrossParent = tweenPrevRep && tweenPrevRep.parent !== tween.parent;
|
|
1789
|
+
// Same parent keyframes take over at their own start, end plus delay equals the next start by construction.
|
|
1790
|
+
// Cross parent siblings take over at their update start.
|
|
1791
|
+
// Negative delay siblings take over at their own start instead.
|
|
1792
|
+
const tweenNextRepTakeover = !tweenNextRep || tweenNextRep._isOverridden ? tweenAbsEndTime :
|
|
1793
|
+
tweenNextRep.parent === tween.parent ? tweenAbsEndTime + tweenNextRep._delay :
|
|
1794
|
+
tweenNextRep._absoluteStartTime < tweenNextRep._absoluteUpdateStartTime ? tweenNextRep._absoluteStartTime : tweenNextRep._absoluteUpdateStartTime;
|
|
1701
1795
|
|
|
1702
1796
|
if ((forcedRender || (
|
|
1703
|
-
|
|
1704
|
-
(tweenCurrentTime !==
|
|
1705
|
-
|
|
1797
|
+
// Tail keyframes always re-evaluate the gate so an earlier keyframe cannot leave the target stale by writing past its own range after a backward seek.
|
|
1798
|
+
(tweenCurrentTime !== tweenChangeDuration || absoluteTime <= tweenNextRepTakeover ||
|
|
1799
|
+
(tweenPrevRep && !tweenPrevRepIsCrossParent && (!tweenNextRep || tweenNextRep.parent !== tween.parent))) &&
|
|
1800
|
+
// A cross parent tween re-renders its from value from the previous sibling truncated end so the handoff gap holds.
|
|
1801
|
+
// A keyframe re-renders its from revert while the next keyframe time is stale so a backward jump over its range cannot leave the next value in place.
|
|
1802
|
+
(tweenCurrentTime !== 0 || absoluteTime >= tween._absoluteStartTime ||
|
|
1803
|
+
(tweenPrevRepIsCrossParent && !tween._hasFromValue && !tweenPrevRep._isOverridden && absoluteTime >= tweenPrevRepEndTime) ||
|
|
1804
|
+
(tweenNextRep && !tweenNextRep._isOverridden && tweenNextRep.parent === tween.parent && tweenNextRep._currentTime !== 0 && iterationTime < tweenNextRep._startTime))
|
|
1805
|
+
)) &&
|
|
1806
|
+
// Non-first keyframes wait until the iteration reaches their own start before rendering, so the previous keyframe can handle the from-revert when scrubbed backward past this tween's range.
|
|
1807
|
+
(!tweenPrevRep || tweenPrevRepIsCrossParent || iterationTime >= tween._startTime) &&
|
|
1808
|
+
(!tweenHasComposition || (
|
|
1706
1809
|
!tween._isOverridden &&
|
|
1707
1810
|
(!tween._isOverlapped || absoluteTime <= tweenAbsEndTime) &&
|
|
1708
|
-
|
|
1709
|
-
(!
|
|
1811
|
+
// The next sibling owns the value past its takeover point, so yielding there keeps writes single owner in both directions.
|
|
1812
|
+
(!tweenNextRep || tweenNextRep._isOverridden || absoluteTime <= tweenNextRepTakeover) &&
|
|
1813
|
+
// The previous sibling owns the value up to its truncated end.
|
|
1814
|
+
// Cross parent tweens take over the hold from that point, explicit from values wait for their own start.
|
|
1815
|
+
(!tweenPrevRep || (tweenPrevRep._isOverridden || (!tweenPrevRepIsCrossParent ?
|
|
1816
|
+
absoluteTime >= tweenPrevRepEndTime + tween._delay :
|
|
1817
|
+
absoluteTime >= tween._absoluteStartTime || (!tween._hasFromValue && absoluteTime >= tweenPrevRepEndTime))))
|
|
1710
1818
|
))
|
|
1711
1819
|
) {
|
|
1712
1820
|
|
|
@@ -1717,7 +1825,7 @@
|
|
|
1717
1825
|
const tweenType = tween._tweenType;
|
|
1718
1826
|
const tweenIsObject = tweenType === tweenTypes.OBJECT;
|
|
1719
1827
|
const tweenIsNumber = tweenValueType === valueTypes.NUMBER;
|
|
1720
|
-
// Only round the in-between frames values if the final value is a string
|
|
1828
|
+
// Only round the in-between frames values if the final value is a string. Object targets consume raw numbers, so rounding is dead work there.
|
|
1721
1829
|
const tweenPrecision = (tweenIsNumber && tweenIsObject) || tweenProgress === 0 || tweenProgress === 1 ? -1 : globals.precision;
|
|
1722
1830
|
|
|
1723
1831
|
// Recompose tween value
|
|
@@ -1733,7 +1841,22 @@
|
|
|
1733
1841
|
number = /** @type {Number} */(tweenModifier(round$1(lerp$1(tween._fromNumber, tween._toNumber, tweenProgress), tweenPrecision)));
|
|
1734
1842
|
value = `${number}${tween._unit}`;
|
|
1735
1843
|
} else if (tweenValueType === valueTypes.COLOR) {
|
|
1736
|
-
|
|
1844
|
+
const ns = tween._numbers;
|
|
1845
|
+
const fn = tween._fromNumbers;
|
|
1846
|
+
const tn = tween._toNumbers;
|
|
1847
|
+
const omt = 1 - tweenProgress;
|
|
1848
|
+
const fr = fn[0], fg = fn[1], fb = fn[2];
|
|
1849
|
+
const tr = tn[0], tg = tn[1], tb = tn[2];
|
|
1850
|
+
// RGB channels lerp in pseudo-linear space (square inputs, sqrt result) to approximate gamma-correct blending.
|
|
1851
|
+
// See https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear.
|
|
1852
|
+
ns[0] = /** @type {Number} */(tweenModifier(Math.sqrt(fr * fr * omt + tr * tr * tweenProgress)));
|
|
1853
|
+
ns[1] = /** @type {Number} */(tweenModifier(Math.sqrt(fg * fg * omt + tg * tg * tweenProgress)));
|
|
1854
|
+
ns[2] = /** @type {Number} */(tweenModifier(Math.sqrt(fb * fb * omt + tb * tb * tweenProgress)));
|
|
1855
|
+
ns[3] = /** @type {Number} */(tweenModifier(lerp$1(fn[3], tn[3], tweenProgress)));
|
|
1856
|
+
// The rgba string is built only for the dispatch path or the internalRender composition tick (setters handles the color comp)
|
|
1857
|
+
if (!tween._setter || internalRender) {
|
|
1858
|
+
value = `rgba(${round$1(ns[0], 0)},${round$1(ns[1], 0)},${round$1(ns[2], 0)},${ns[3]})`;
|
|
1859
|
+
}
|
|
1737
1860
|
} else if (tweenValueType === valueTypes.COMPLEX) {
|
|
1738
1861
|
value = composeComplexValue(tween, tweenProgress, tweenPrecision);
|
|
1739
1862
|
}
|
|
@@ -1748,7 +1871,9 @@
|
|
|
1748
1871
|
const tweenProperty = tween.property;
|
|
1749
1872
|
tweenTarget = tween.target;
|
|
1750
1873
|
|
|
1751
|
-
if (
|
|
1874
|
+
if (tween._setter) {
|
|
1875
|
+
tween._setter(tweenTarget, number, tween);
|
|
1876
|
+
} else if (tweenIsObject) {
|
|
1752
1877
|
tweenTarget[tweenProperty] = value;
|
|
1753
1878
|
} else if (tweenType === tweenTypes.ATTRIBUTE) {
|
|
1754
1879
|
/** @type {DOMTarget} */(tweenTarget).setAttribute(tweenProperty, /** @type {String} */(value));
|
|
@@ -1776,6 +1901,9 @@
|
|
|
1776
1901
|
tween._value = value;
|
|
1777
1902
|
}
|
|
1778
1903
|
|
|
1904
|
+
} else if (tweenCurrentTime && tweenPrevRep && !tweenPrevRepIsCrossParent && iterationTime < tween._startTime) {
|
|
1905
|
+
// Mark the keyframe as reverted when the playhead moves before its start, the previous keyframe owns the from revert and writes it once.
|
|
1906
|
+
tween._currentTime = 0;
|
|
1779
1907
|
}
|
|
1780
1908
|
|
|
1781
1909
|
if (tweenTransformsNeedUpdate && tween._renderTransforms) {
|
|
@@ -1883,6 +2011,8 @@
|
|
|
1883
2011
|
|
|
1884
2012
|
forEachChildren(tl, (/** @type {JSAnimation} */child) => {
|
|
1885
2013
|
const childTime = round$1((tlChildrenTime - child._offset) * child._speed, 12); // Rounding is needed when using seconds
|
|
2014
|
+
// Skip past-end siblings on backward iteration so their progress=1 to-values don't render last and overwrite the active sibling's write. Compare against _delay + duration so children with a normalized delay are not skipped while still inside their active range.
|
|
2015
|
+
if (tlIsRunningBackwards && childTime > child._delay + child.duration) return;
|
|
1886
2016
|
const childTickMode = child._fps < tl._fps ? child.requestTick(tlCildrenTickTime) : tickMode;
|
|
1887
2017
|
tlChildrenHasRendered += render(child, childTime, muteCallbacks, internalRender, childTickMode);
|
|
1888
2018
|
if (!child.completed && tlChildrenHaveCompleted) tlChildrenHaveCompleted = false;
|
|
@@ -1959,7 +2089,20 @@
|
|
|
1959
2089
|
const tweenType = tween._tweenType;
|
|
1960
2090
|
const originalInlinedValue = tween._inlineValue;
|
|
1961
2091
|
const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
|
|
1962
|
-
if (
|
|
2092
|
+
if (tween._setter) {
|
|
2093
|
+
if (!inlineStylesOnly && !tweenHadNoInlineValue) {
|
|
2094
|
+
// Re-seed the original value to the _number / _numbers props so the setter can write the original state instead of re-applying the current frame.
|
|
2095
|
+
decomposeRawValue(originalInlinedValue, decomposedOriginalValue);
|
|
2096
|
+
if (decomposedOriginalValue.d) {
|
|
2097
|
+
const src = decomposedOriginalValue.d;
|
|
2098
|
+
const dst = tween._numbers;
|
|
2099
|
+
for (let i = 0, l = src.length; i < l; i++) dst[i] = src[i];
|
|
2100
|
+
} else {
|
|
2101
|
+
tween._number = decomposedOriginalValue.n;
|
|
2102
|
+
}
|
|
2103
|
+
tween._setter(tween.target, tween._number, tween);
|
|
2104
|
+
}
|
|
2105
|
+
} else if (tweenType === tweenTypes.OBJECT) {
|
|
1963
2106
|
if (!inlineStylesOnly && !tweenHadNoInlineValue) {
|
|
1964
2107
|
tweenTarget[tweenProperty] = originalInlinedValue;
|
|
1965
2108
|
}
|
|
@@ -2036,8 +2179,6 @@
|
|
|
2036
2179
|
/** @type {Number} */
|
|
2037
2180
|
this._lastTime = initTime;
|
|
2038
2181
|
/** @type {Number} */
|
|
2039
|
-
this._scheduledTime = 0;
|
|
2040
|
-
/** @type {Number} */
|
|
2041
2182
|
this._frameDuration = K / maxFps;
|
|
2042
2183
|
/** @type {Number} */
|
|
2043
2184
|
this._fps = maxFps;
|
|
@@ -2056,14 +2197,12 @@
|
|
|
2056
2197
|
}
|
|
2057
2198
|
|
|
2058
2199
|
set fps(frameRate) {
|
|
2059
|
-
const previousFrameDuration = this._frameDuration;
|
|
2060
2200
|
const fr = +frameRate;
|
|
2061
2201
|
const fps = fr < minValue ? minValue : fr;
|
|
2062
2202
|
const frameDuration = K / fps;
|
|
2063
2203
|
if (fps > defaults.frameRate) defaults.frameRate = fps;
|
|
2064
2204
|
this._fps = fps;
|
|
2065
2205
|
this._frameDuration = frameDuration;
|
|
2066
|
-
this._scheduledTime += frameDuration - previousFrameDuration;
|
|
2067
2206
|
}
|
|
2068
2207
|
|
|
2069
2208
|
get speed() {
|
|
@@ -2080,17 +2219,17 @@
|
|
|
2080
2219
|
* @return {tickModes}
|
|
2081
2220
|
*/
|
|
2082
2221
|
requestTick(time) {
|
|
2083
|
-
const scheduledTime = this._scheduledTime;
|
|
2084
|
-
this._lastTickTime = time;
|
|
2085
|
-
// If the current time is lower than the scheduled time
|
|
2086
|
-
// this means not enough time has passed to hit one frameDuration
|
|
2087
|
-
// so skip that frame
|
|
2088
|
-
if (time < scheduledTime) return tickModes.NONE;
|
|
2089
2222
|
const frameDuration = this._frameDuration;
|
|
2090
|
-
const
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2223
|
+
const elapsed = time - this._lastTickTime;
|
|
2224
|
+
const scaled = frameDuration * .25;
|
|
2225
|
+
const tolerance = scaled < 4 ? scaled : 4;
|
|
2226
|
+
// Tolerance prevents dropping frames that arrive a bit early due to RAF jitter
|
|
2227
|
+
// typically <= ~25% of frame duration and capped at 4ms so it doesn't dominate at high fps.
|
|
2228
|
+
// e.g. at 60fps (frameDuration=16.667ms) a frame arriving after 15ms:
|
|
2229
|
+
// - without tolerance: 15 < 16.667 -> skip
|
|
2230
|
+
// - with tolerance: 15 + 4 >= 16.667 -> tick
|
|
2231
|
+
if (elapsed + tolerance < frameDuration) return tickModes.NONE;
|
|
2232
|
+
this._lastTickTime = elapsed >= frameDuration ? time - (elapsed % frameDuration) : time;
|
|
2094
2233
|
return tickModes.AUTO;
|
|
2095
2234
|
}
|
|
2096
2235
|
|
|
@@ -2250,7 +2389,9 @@
|
|
|
2250
2389
|
}
|
|
2251
2390
|
|
|
2252
2391
|
set speed(playbackRate) {
|
|
2253
|
-
|
|
2392
|
+
const speed = playbackRate * globals.timeScale;
|
|
2393
|
+
if (this._speed === speed) return;
|
|
2394
|
+
this._speed = speed;
|
|
2254
2395
|
forEachChildren(this, (/** @type {Tickable} */child) => child.speed = child._speed);
|
|
2255
2396
|
}
|
|
2256
2397
|
|
|
@@ -2383,7 +2524,7 @@
|
|
|
2383
2524
|
if (prevSibling) {
|
|
2384
2525
|
|
|
2385
2526
|
const prevParent = prevSibling.parent;
|
|
2386
|
-
const prevAbsEndTime = prevSibling.
|
|
2527
|
+
const prevAbsEndTime = prevSibling._absoluteEndTime;
|
|
2387
2528
|
|
|
2388
2529
|
// Handle looped animations tween
|
|
2389
2530
|
|
|
@@ -2409,7 +2550,8 @@
|
|
|
2409
2550
|
|
|
2410
2551
|
}
|
|
2411
2552
|
|
|
2412
|
-
|
|
2553
|
+
// Read the precision-matched update-start instead of subtracting tween._delay live so sequential keyframes touching at a boundary don't trigger a phantom overlap from float drift.
|
|
2554
|
+
const absoluteUpdateStartTime = tween._absoluteUpdateStartTime;
|
|
2413
2555
|
|
|
2414
2556
|
if (prevAbsEndTime > absoluteUpdateStartTime) {
|
|
2415
2557
|
|
|
@@ -2429,37 +2571,41 @@
|
|
|
2429
2571
|
}
|
|
2430
2572
|
}
|
|
2431
2573
|
|
|
2432
|
-
//
|
|
2574
|
+
// Skip the cancel cascade when both tweens share the same parent timeline, a timeline cannot replace itself.
|
|
2575
|
+
const tweenParentTL = tween.parent.parent;
|
|
2576
|
+
if (!tweenParentTL || tweenParentTL !== prevParent.parent) {
|
|
2433
2577
|
|
|
2434
|
-
|
|
2578
|
+
let pausePrevParentAnimation = true;
|
|
2435
2579
|
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2580
|
+
forEachChildren(prevParent, (/** @type Tween */t) => {
|
|
2581
|
+
if (!t._isOverlapped) pausePrevParentAnimation = false;
|
|
2582
|
+
});
|
|
2439
2583
|
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2584
|
+
if (pausePrevParentAnimation) {
|
|
2585
|
+
const prevParentTL = prevParent.parent;
|
|
2586
|
+
if (prevParentTL) {
|
|
2587
|
+
let pausePrevParentTL = true;
|
|
2588
|
+
forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
|
|
2589
|
+
if (a !== prevParent) {
|
|
2590
|
+
forEachChildren(a, (/** @type Tween */t) => {
|
|
2591
|
+
if (!t._isOverlapped) pausePrevParentTL = false;
|
|
2592
|
+
});
|
|
2593
|
+
}
|
|
2594
|
+
});
|
|
2595
|
+
if (pausePrevParentTL) {
|
|
2596
|
+
prevParentTL.cancel();
|
|
2449
2597
|
}
|
|
2450
|
-
}
|
|
2451
|
-
|
|
2452
|
-
|
|
2598
|
+
} else {
|
|
2599
|
+
prevParent.cancel();
|
|
2600
|
+
// Previously, calling .cancel() on a timeline child would affect the render order of other children
|
|
2601
|
+
// Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
|
|
2602
|
+
// This is no longer needed since timeline tween composition is now handled separately
|
|
2603
|
+
// Keeping this here for reference
|
|
2604
|
+
// prevParent.completed = true;
|
|
2605
|
+
// prevParent.pause();
|
|
2453
2606
|
}
|
|
2454
|
-
} else {
|
|
2455
|
-
prevParent.cancel();
|
|
2456
|
-
// Previously, calling .cancel() on a timeline child would affect the render order of other children
|
|
2457
|
-
// Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
|
|
2458
|
-
// This is no longer needed since timeline tween composition is now handled separately
|
|
2459
|
-
// Keeping this here for reference
|
|
2460
|
-
// prevParent.completed = true;
|
|
2461
|
-
// prevParent.pause();
|
|
2462
2607
|
}
|
|
2608
|
+
|
|
2463
2609
|
}
|
|
2464
2610
|
|
|
2465
2611
|
}
|
|
@@ -2514,14 +2660,12 @@
|
|
|
2514
2660
|
tween._number = 0;
|
|
2515
2661
|
lookupTween._fromNumber = toNumber;
|
|
2516
2662
|
|
|
2517
|
-
if (tween._toNumbers) {
|
|
2663
|
+
if (tween._toNumbers.length) {
|
|
2518
2664
|
const toNumbers = cloneArray(tween._toNumbers);
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
});
|
|
2524
|
-
}
|
|
2665
|
+
toNumbers.forEach((value, i) => {
|
|
2666
|
+
tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
|
|
2667
|
+
tween._toNumbers[i] = 0;
|
|
2668
|
+
});
|
|
2525
2669
|
lookupTween._fromNumbers = toNumbers;
|
|
2526
2670
|
}
|
|
2527
2671
|
|
|
@@ -3222,18 +3366,16 @@
|
|
|
3222
3366
|
function registerTargets(targets) {
|
|
3223
3367
|
const parsedTargetsArray = parseTargets(targets);
|
|
3224
3368
|
const parsedTargetsLength = parsedTargetsArray.length;
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
target[transformsSymbol] = {};
|
|
3236
|
-
}
|
|
3369
|
+
for (let i = 0; i < parsedTargetsLength; i++) {
|
|
3370
|
+
const target = parsedTargetsArray[i];
|
|
3371
|
+
if (!target[isRegisteredTargetSymbol]) {
|
|
3372
|
+
target[isRegisteredTargetSymbol] = true;
|
|
3373
|
+
const isSvgType = isSvg(target);
|
|
3374
|
+
const isDom = /** @type {DOMTarget} */(target).nodeType || isSvgType;
|
|
3375
|
+
if (isDom) {
|
|
3376
|
+
target[isDomSymbol] = true;
|
|
3377
|
+
target[isSvgSymbol] = isSvgType;
|
|
3378
|
+
target[transformsSymbol] = {};
|
|
3237
3379
|
}
|
|
3238
3380
|
}
|
|
3239
3381
|
}
|
|
@@ -3355,8 +3497,8 @@
|
|
|
3355
3497
|
|
|
3356
3498
|
/**
|
|
3357
3499
|
* @typedef {Object} EasesFunctions
|
|
3358
|
-
* @property {
|
|
3359
|
-
* @property {
|
|
3500
|
+
* @property {EasingFunction} linear
|
|
3501
|
+
* @property {EasingFunction} none
|
|
3360
3502
|
* @property {PowerEasing} in
|
|
3361
3503
|
* @property {PowerEasing} out
|
|
3362
3504
|
* @property {PowerEasing} inOut
|
|
@@ -3588,6 +3730,11 @@
|
|
|
3588
3730
|
|
|
3589
3731
|
super(/** @type {TimerParams & AnimationParams} */(parameters), parent, parentPosition);
|
|
3590
3732
|
|
|
3733
|
+
/** @type {Tween} */
|
|
3734
|
+
this._head;
|
|
3735
|
+
/** @type {Tween} */
|
|
3736
|
+
this._tail;
|
|
3737
|
+
|
|
3591
3738
|
++JSAnimationId;
|
|
3592
3739
|
|
|
3593
3740
|
const parsedTargets = registerTargets(targets);
|
|
@@ -3644,6 +3791,7 @@
|
|
|
3644
3791
|
if (isKey(p)) {
|
|
3645
3792
|
|
|
3646
3793
|
const tweenType = getTweenType(target, p);
|
|
3794
|
+
const adapterProp = resolveAdapterEntry(target, p);
|
|
3647
3795
|
|
|
3648
3796
|
const propName = sanitizePropertyName(p, target, tweenType);
|
|
3649
3797
|
|
|
@@ -3727,7 +3875,7 @@
|
|
|
3727
3875
|
} else {
|
|
3728
3876
|
tweenToValue = computedToValue;
|
|
3729
3877
|
}
|
|
3730
|
-
const tweenFromValue = getFunctionValue(key.from, target, ti, tl,
|
|
3878
|
+
const tweenFromValue = getFunctionValue(key.from, target, ti, tl, fromFunctionStore, prevSiblingTween);
|
|
3731
3879
|
const easeToParse = key.ease || tEasing;
|
|
3732
3880
|
|
|
3733
3881
|
const easeFunctionResult = getFunctionValue(easeToParse, target, ti, tl, null, prevSiblingTween);
|
|
@@ -3745,9 +3893,13 @@
|
|
|
3745
3893
|
const hasToValue = !isUnd(tweenToValue);
|
|
3746
3894
|
const isFromToArray = isArr(tweenToValue);
|
|
3747
3895
|
const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
|
|
3896
|
+
// Capture the update-start in local time, the previous sibling's end for keyframes after the first, zero for the first keyframe. Used to derive a precision-matched _absoluteUpdateStartTime below.
|
|
3897
|
+
const tweenUpdateStartLocal = prevTween ? lastTweenChangeEndTime : 0;
|
|
3748
3898
|
const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
|
|
3749
3899
|
// Rounding is necessary here to minimize floating point errors when working in seconds
|
|
3750
3900
|
const absoluteStartTime = round$1(absoluteOffsetTime + tweenStartTime, 12);
|
|
3901
|
+
// Match the rounding pattern of prevSibling._absoluteEndTime so the composition overlap check compares cleanly when keyframes touch at a boundary.
|
|
3902
|
+
const absoluteUpdateStartTime = round$1(absoluteOffsetTime + tweenUpdateStartLocal, 12);
|
|
3751
3903
|
|
|
3752
3904
|
// Force a onRender callback if the animation contains at least one from value and autoplay is set to false
|
|
3753
3905
|
if (!shouldTriggerRender && (hasFromvalue || isFromToArray)) shouldTriggerRender = 1;
|
|
@@ -3756,9 +3908,9 @@
|
|
|
3756
3908
|
|
|
3757
3909
|
if (tweenComposition !== compositionTypes.none) {
|
|
3758
3910
|
let nextSibling = siblings._head;
|
|
3759
|
-
//
|
|
3760
|
-
while (nextSibling &&
|
|
3761
|
-
prevSibling = nextSibling;
|
|
3911
|
+
// Walk prior siblings up to the new tween, skipping overridden ones so the chain resolves to the latest live value instead of stopping at the first override.
|
|
3912
|
+
while (nextSibling && nextSibling._absoluteStartTime <= absoluteStartTime) {
|
|
3913
|
+
if (!nextSibling._isOverridden) prevSibling = nextSibling;
|
|
3762
3914
|
nextSibling = nextSibling._nextRep;
|
|
3763
3915
|
// Overrides all the next siblings if the next sibling starts at the same time of after as the new tween start time
|
|
3764
3916
|
if (nextSibling && nextSibling._absoluteStartTime >= absoluteStartTime) {
|
|
@@ -3812,8 +3964,8 @@
|
|
|
3812
3964
|
if (prevTween) {
|
|
3813
3965
|
decomposeTweenValue(prevTween, fromTargetObject);
|
|
3814
3966
|
} else {
|
|
3815
|
-
decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
|
|
3816
3967
|
// No need to get and parse the original value if the tween is part of a timeline and has a previous sibling part of the same timeline
|
|
3968
|
+
decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
|
|
3817
3969
|
getOriginalAnimatableValue(target, propName, tweenType, inlineStylesStore), fromTargetObject);
|
|
3818
3970
|
}
|
|
3819
3971
|
}
|
|
@@ -3852,8 +4004,7 @@
|
|
|
3852
4004
|
const colorValue = fromTargetObject.t === valueTypes.COLOR ? fromTargetObject : toTargetObject;
|
|
3853
4005
|
const notColorValue = fromTargetObject.t === valueTypes.COLOR ? toTargetObject : fromTargetObject;
|
|
3854
4006
|
notColorValue.t = valueTypes.COLOR;
|
|
3855
|
-
notColorValue.
|
|
3856
|
-
notColorValue.d = [0, 0, 0, 1];
|
|
4007
|
+
notColorValue.d = colorValue.d.map(() => 0);
|
|
3857
4008
|
}
|
|
3858
4009
|
}
|
|
3859
4010
|
|
|
@@ -3883,6 +4034,16 @@
|
|
|
3883
4034
|
let inlineValue = inlineStylesStore[propName];
|
|
3884
4035
|
if (!isNil(inlineValue)) inlineStylesStore[propName] = null;
|
|
3885
4036
|
|
|
4037
|
+
// Resolve the adapter setter once so render skips the lookup per frame.
|
|
4038
|
+
const tweenSetter = adapterProp ? adapterProp.set : null;
|
|
4039
|
+
|
|
4040
|
+
// Rounding is necessary here to minimize floating point errors when working in seconds
|
|
4041
|
+
lastTweenChangeEndTime = round$1(tweenStartTime + tweenUpdateDuration, 12);
|
|
4042
|
+
|
|
4043
|
+
const fromD = fromTargetObject.d;
|
|
4044
|
+
const toD = toTargetObject.d;
|
|
4045
|
+
const toS = toTargetObject.s;
|
|
4046
|
+
|
|
3886
4047
|
/** @type {Tween} */
|
|
3887
4048
|
const tween = {
|
|
3888
4049
|
parent: this,
|
|
@@ -3893,12 +4054,12 @@
|
|
|
3893
4054
|
_toFunc: toFunctionStore.func,
|
|
3894
4055
|
_fromFunc: fromFunctionStore.func,
|
|
3895
4056
|
_ease: parseEase(tweenEasing),
|
|
3896
|
-
_fromNumbers: cloneArray(
|
|
3897
|
-
_toNumbers: cloneArray(
|
|
3898
|
-
_strings: cloneArray(
|
|
4057
|
+
_fromNumbers: fromD ? cloneArray(fromD) : emptyArray,
|
|
4058
|
+
_toNumbers: toD ? cloneArray(toD) : emptyArray,
|
|
4059
|
+
_strings: toS ? cloneArray(toS) : emptyArray,
|
|
3899
4060
|
_fromNumber: fromTargetObject.n,
|
|
3900
4061
|
_toNumber: toTargetObject.n,
|
|
3901
|
-
_numbers: cloneArray(
|
|
4062
|
+
_numbers: fromD ? cloneArray(fromD) : emptyArray, // For additive tween and animatables
|
|
3902
4063
|
_number: fromTargetObject.n, // For additive tween and animatables
|
|
3903
4064
|
_unit: toTargetObject.u,
|
|
3904
4065
|
_modifier: tweenModifier,
|
|
@@ -3908,8 +4069,12 @@
|
|
|
3908
4069
|
_updateDuration: tweenUpdateDuration,
|
|
3909
4070
|
_changeDuration: tweenUpdateDuration,
|
|
3910
4071
|
_absoluteStartTime: absoluteStartTime,
|
|
4072
|
+
_absoluteUpdateStartTime: absoluteUpdateStartTime,
|
|
4073
|
+
_absoluteEndTime: round$1(absoluteOffsetTime + lastTweenChangeEndTime, 12),
|
|
4074
|
+
_hasFromValue: hasFromvalue || isFromToArray ? 1 : 0,
|
|
3911
4075
|
// NOTE: Investigate bit packing to stores ENUM / BOOL
|
|
3912
4076
|
_tweenType: tweenType,
|
|
4077
|
+
_setter: tweenSetter,
|
|
3913
4078
|
_valueType: toTargetObject.t,
|
|
3914
4079
|
_composition: tweenComposition,
|
|
3915
4080
|
_isOverlapped: 0,
|
|
@@ -3932,10 +4097,11 @@
|
|
|
3932
4097
|
const vt = tween._valueType;
|
|
3933
4098
|
if (vt === valueTypes.COMPLEX) {
|
|
3934
4099
|
tween._value = composeComplexValue(tween, 1, -1);
|
|
3935
|
-
} else if (vt === valueTypes.COLOR) {
|
|
3936
|
-
tween._value = composeColorValue(tween, 1, -1);
|
|
3937
4100
|
} else if (vt === valueTypes.UNIT) {
|
|
3938
4101
|
tween._value = `${tweenModifier(tween._toNumber)}${tween._unit}`;
|
|
4102
|
+
} else if (vt === valueTypes.COLOR) {
|
|
4103
|
+
const d = toTargetObject.d;
|
|
4104
|
+
tween._value = `rgba(${round$1(d[0], 0)},${round$1(d[1], 0)},${round$1(d[2], 0)},${d[3]})`;
|
|
3939
4105
|
} else {
|
|
3940
4106
|
tween._value = tweenModifier(tween._toNumber);
|
|
3941
4107
|
}
|
|
@@ -3943,8 +4109,7 @@
|
|
|
3943
4109
|
if (isNaN(firstTweenChangeStartTime)) {
|
|
3944
4110
|
firstTweenChangeStartTime = tween._startTime;
|
|
3945
4111
|
}
|
|
3946
|
-
|
|
3947
|
-
lastTweenChangeEndTime = round$1(tweenStartTime + tweenUpdateDuration, 12);
|
|
4112
|
+
|
|
3948
4113
|
prevTween = tween;
|
|
3949
4114
|
animationAnimationLength++;
|
|
3950
4115
|
|
|
@@ -4050,8 +4215,11 @@
|
|
|
4050
4215
|
tween._updateDuration = normalizeTime(tween._updateDuration * timeScale);
|
|
4051
4216
|
tween._changeDuration = normalizeTime(tween._changeDuration * timeScale);
|
|
4052
4217
|
tween._currentTime *= timeScale;
|
|
4218
|
+
tween._delay *= timeScale;
|
|
4053
4219
|
tween._startTime *= timeScale;
|
|
4054
4220
|
tween._absoluteStartTime *= timeScale;
|
|
4221
|
+
tween._absoluteUpdateStartTime *= timeScale;
|
|
4222
|
+
tween._absoluteEndTime *= timeScale;
|
|
4055
4223
|
});
|
|
4056
4224
|
return super.stretch(newDuration);
|
|
4057
4225
|
}
|
|
@@ -4180,8 +4348,6 @@
|
|
|
4180
4348
|
|
|
4181
4349
|
|
|
4182
4350
|
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
4351
|
/**
|
|
4186
4352
|
* @param {Timeline} tl
|
|
4187
4353
|
* @return {Number}
|
|
@@ -4374,13 +4540,21 @@
|
|
|
4374
4540
|
if (!isUnd(synced) && !isUnd(/** @type {WAAPIAnimation} */(synced).persist)) {
|
|
4375
4541
|
/** @type {WAAPIAnimation} */(synced).persist = true;
|
|
4376
4542
|
}
|
|
4377
|
-
|
|
4543
|
+
const editor = globals.editor;
|
|
4544
|
+
const childHook = editor && editor.addTimelineChild;
|
|
4545
|
+
if (editor && editor.addTimelineSync) {
|
|
4546
|
+
position = editor.addTimelineSync(synced, position, this.id);
|
|
4547
|
+
editor.addTimelineChild = null; // Suppress the per-child hook for the internal .add, sync already registered.
|
|
4548
|
+
}
|
|
4549
|
+
const result = this.add(synced, { currentTime: [0, duration], duration, delay: 0, ease: 'linear', playbackEase: 'linear' }, position);
|
|
4550
|
+
if (editor) editor.addTimelineChild = childHook;
|
|
4551
|
+
return result;
|
|
4378
4552
|
}
|
|
4379
4553
|
|
|
4380
4554
|
/**
|
|
4381
4555
|
* @param {TargetsParam} targets
|
|
4382
4556
|
* @param {AnimationParams} parameters
|
|
4383
|
-
* @param {TimelinePosition} [position]
|
|
4557
|
+
* @param {TimelinePosition|StaggerFunction<Number|String>|TweakRegister} [position]
|
|
4384
4558
|
* @return {this}
|
|
4385
4559
|
*/
|
|
4386
4560
|
set(targets, parameters, position) {
|
|
@@ -4397,6 +4571,7 @@
|
|
|
4397
4571
|
*/
|
|
4398
4572
|
call(callback, position) {
|
|
4399
4573
|
if (isUnd(callback) || callback && !isFnc(callback)) return this;
|
|
4574
|
+
if (globals.editor && globals.editor.addTimelineCall) position = globals.editor.addTimelineCall(callback, position, this.id);
|
|
4400
4575
|
return this.add({ duration: 0, delay: 0, onComplete: () => callback(this) }, position);
|
|
4401
4576
|
}
|
|
4402
4577
|
|
|
@@ -4408,6 +4583,7 @@
|
|
|
4408
4583
|
*/
|
|
4409
4584
|
label(labelName, position) {
|
|
4410
4585
|
if (isUnd(labelName) || labelName && !isStr(labelName)) return this;
|
|
4586
|
+
if (globals.editor && globals.editor.addTimelineLabel) position = globals.editor.addTimelineLabel(labelName, position, this.id);
|
|
4411
4587
|
this.labels[labelName] = parseTimelinePosition(this, position);
|
|
4412
4588
|
return this;
|
|
4413
4589
|
}
|
|
@@ -4516,6 +4692,7 @@
|
|
|
4516
4692
|
const callbacksAnimationParams = { v: 1, autoplay: false };
|
|
4517
4693
|
const properties = {};
|
|
4518
4694
|
this.targets = [];
|
|
4695
|
+
/** @type {Record<String, JSAnimation>} */
|
|
4519
4696
|
this.animations = {};
|
|
4520
4697
|
/** @type {JSAnimation|null} */
|
|
4521
4698
|
this.callbacks = null;
|
|
@@ -5054,6 +5231,9 @@
|
|
|
5054
5231
|
*/
|
|
5055
5232
|
const set = (targets, parameters) => {
|
|
5056
5233
|
if (isUnd(parameters)) return;
|
|
5234
|
+
if (globals.editor && globals.editor.addSet) {
|
|
5235
|
+
return globals.editor.addSet(targets, parameters);
|
|
5236
|
+
}
|
|
5057
5237
|
parameters.duration = minValue;
|
|
5058
5238
|
// Do not overrides currently active tweens by default
|
|
5059
5239
|
parameters.composition = setValue(parameters.composition, compositionTypes.none);
|
|
@@ -6290,13 +6470,14 @@
|
|
|
6290
6470
|
};
|
|
6291
6471
|
|
|
6292
6472
|
/**
|
|
6293
|
-
* @
|
|
6294
|
-
* @
|
|
6473
|
+
* @template {Tickable | ((...args: any[]) => void) | void} T
|
|
6474
|
+
* @param {(...args: any[]) => T} constructor
|
|
6475
|
+
* @return {(...args: any[]) => T extends void ? () => void : T}
|
|
6295
6476
|
*/
|
|
6296
6477
|
const keepTime = constructor => {
|
|
6297
6478
|
/** @type {Tickable} */
|
|
6298
6479
|
let tracked;
|
|
6299
|
-
return (...args) => {
|
|
6480
|
+
return /** @type {(...args: any[]) => T extends void ? () => void : T} */(/** @type {*} */((...args) => {
|
|
6300
6481
|
let currentIteration, currentIterationProgress, reversed, alternate, startTime;
|
|
6301
6482
|
if (tracked) {
|
|
6302
6483
|
currentIteration = tracked.currentIteration;
|
|
@@ -6314,7 +6495,7 @@
|
|
|
6314
6495
|
/** @type {Tickable} */(tracked)._startTime = startTime;
|
|
6315
6496
|
}
|
|
6316
6497
|
return cleanup || noop;
|
|
6317
|
-
}
|
|
6498
|
+
}));
|
|
6318
6499
|
};
|
|
6319
6500
|
|
|
6320
6501
|
|
|
@@ -6712,12 +6893,14 @@
|
|
|
6712
6893
|
|
|
6713
6894
|
refreshScrollObservers() {
|
|
6714
6895
|
forEachChildren(this, (/** @type {ScrollObserver} */child) => {
|
|
6896
|
+
if (!child.ready) return;
|
|
6715
6897
|
if (child._debug) {
|
|
6716
6898
|
child.removeDebug();
|
|
6717
6899
|
}
|
|
6718
6900
|
});
|
|
6719
6901
|
this.updateBounds();
|
|
6720
6902
|
forEachChildren(this, (/** @type {ScrollObserver} */child) => {
|
|
6903
|
+
if (!child.ready) return;
|
|
6721
6904
|
child.refresh();
|
|
6722
6905
|
child.onResize(child);
|
|
6723
6906
|
if (child._debug) {
|
|
@@ -9815,11 +9998,12 @@
|
|
|
9815
9998
|
* Adapted from https://bost.ocks.org/mike/shuffle/
|
|
9816
9999
|
*
|
|
9817
10000
|
* @param {Array} items - The array to shuffle (will be modified in-place)
|
|
10001
|
+
* @param {RandomNumberGenerator} [rnd] - Optional RNG matching the random() signature (defaults to random)
|
|
9818
10002
|
* @return {Array} The same array reference, now shuffled
|
|
9819
10003
|
*/
|
|
9820
|
-
const shuffle = items => {
|
|
10004
|
+
const shuffle = (items, rnd = random) => {
|
|
9821
10005
|
let m = items.length, t, i;
|
|
9822
|
-
while (m) { i =
|
|
10006
|
+
while (m) { i = rnd(0, --m); t = items[m]; items[m] = items[i]; items[i] = t; }
|
|
9823
10007
|
return items;
|
|
9824
10008
|
};
|
|
9825
10009
|
|
|
@@ -9864,6 +10048,7 @@
|
|
|
9864
10048
|
let values = [];
|
|
9865
10049
|
let maxValue = 0;
|
|
9866
10050
|
let cachedOffset;
|
|
10051
|
+
let jitterSamples = null;
|
|
9867
10052
|
const from = params.from;
|
|
9868
10053
|
const reversed = params.reversed;
|
|
9869
10054
|
const ease = params.ease;
|
|
@@ -9885,27 +10070,42 @@
|
|
|
9885
10070
|
const val2 = isRange ? parseNumber(val[1]) : 0;
|
|
9886
10071
|
const unitMatch = unitsExecRgx.exec((isRange ? val[1] : val) + emptyString);
|
|
9887
10072
|
const start = params.start || 0 + (isRange ? val1 : 0);
|
|
10073
|
+
const seed = params.seed;
|
|
10074
|
+
const hasSeed = !isUnd(seed) && seed !== false;
|
|
10075
|
+
const rng = hasSeed ? createSeededRandom(seed === true ? 0 : /** @type {Number} */(seed)) : random;
|
|
10076
|
+
const jitter = params.jitter;
|
|
10077
|
+
const hasJitter = !isUnd(jitter);
|
|
10078
|
+
const jitterIsArr = isArr(jitter);
|
|
10079
|
+
const jitterStart = jitterIsArr ? /** @type {[Number,Number]} */(jitter)[0] : /** @type {Number} */(jitter) || 0;
|
|
10080
|
+
const jitterEnd = jitterIsArr ? /** @type {[Number,Number]} */(jitter)[1] : /** @type {Number} */(jitter) || 0;
|
|
9888
10081
|
let fromIndex = fromFirst ? 0 : isNum(from) ? from : 0;
|
|
9889
10082
|
return (target, i, t, _, tl) => {
|
|
9890
10083
|
const [ registeredTarget ] = registerTargets(target);
|
|
9891
10084
|
const total = isUnd(customTotal) ? t.length : customTotal;
|
|
9892
10085
|
const customIndex = !isUnd(useProp) ? isFnc(useProp) ? useProp(registeredTarget, i, total) : getOriginalAnimatableValue(registeredTarget, useProp) : false;
|
|
9893
|
-
const
|
|
10086
|
+
const customIdx = isNum(customIndex) || isStr(customIndex) && isNum(+customIndex) ? +customIndex : i;
|
|
10087
|
+
// Fall back to the natural index when the resolved value lands outside [0, total) so values[staggerIndex] never reads undefined.
|
|
10088
|
+
const staggerIndex = customIdx >= 0 && customIdx < total ? customIdx : i;
|
|
9894
10089
|
if (fromCenter) fromIndex = (total - 1) / 2;
|
|
9895
10090
|
if (fromLast) fromIndex = total - 1;
|
|
9896
10091
|
if (!values.length) {
|
|
9897
10092
|
if (autoGrid) {
|
|
9898
10093
|
let hasPositions = true;
|
|
10094
|
+
let has3D = false;
|
|
9899
10095
|
let minPosX = Infinity;
|
|
9900
10096
|
let minPosY = Infinity;
|
|
10097
|
+
let minPosZ = Infinity;
|
|
9901
10098
|
let maxPosX = -Infinity;
|
|
9902
10099
|
let maxPosY = -Infinity;
|
|
10100
|
+
let maxPosZ = -Infinity;
|
|
9903
10101
|
const pxArr = [];
|
|
9904
10102
|
const pyArr = [];
|
|
10103
|
+
const pzArr = [];
|
|
9905
10104
|
for (let index = 0; index < total; index++) {
|
|
9906
10105
|
const el = t[index];
|
|
9907
10106
|
let px = 0;
|
|
9908
10107
|
let py = 0;
|
|
10108
|
+
let pz = 0;
|
|
9909
10109
|
let found = false;
|
|
9910
10110
|
if (el && isFnc(el.getBoundingClientRect)) {
|
|
9911
10111
|
const rect = el.getBoundingClientRect();
|
|
@@ -9917,6 +10117,10 @@
|
|
|
9917
10117
|
if (obj && isNum(obj.x) && isNum(obj.y)) {
|
|
9918
10118
|
px = obj.x;
|
|
9919
10119
|
py = obj.y;
|
|
10120
|
+
if (isNum(obj.z)) {
|
|
10121
|
+
pz = obj.z;
|
|
10122
|
+
has3D = true;
|
|
10123
|
+
}
|
|
9920
10124
|
found = true;
|
|
9921
10125
|
}
|
|
9922
10126
|
}
|
|
@@ -9926,42 +10130,52 @@
|
|
|
9926
10130
|
}
|
|
9927
10131
|
pxArr.push(px);
|
|
9928
10132
|
pyArr.push(py);
|
|
10133
|
+
pzArr.push(pz);
|
|
9929
10134
|
if (px < minPosX) minPosX = px;
|
|
9930
10135
|
if (py < minPosY) minPosY = py;
|
|
10136
|
+
if (pz < minPosZ) minPosZ = pz;
|
|
9931
10137
|
if (px > maxPosX) maxPosX = px;
|
|
9932
10138
|
if (py > maxPosY) maxPosY = py;
|
|
10139
|
+
if (pz > maxPosZ) maxPosZ = pz;
|
|
9933
10140
|
}
|
|
9934
10141
|
if (hasPositions) {
|
|
9935
10142
|
let fX = pxArr[0];
|
|
9936
10143
|
let fY = pyArr[0];
|
|
10144
|
+
let fZ = pzArr[0];
|
|
9937
10145
|
if (fromArr) {
|
|
9938
10146
|
fX = minPosX + from[0] * (maxPosX - minPosX);
|
|
9939
10147
|
fY = minPosY + from[1] * (maxPosY - minPosY);
|
|
10148
|
+
fZ = has3D ? minPosZ + (from.length >= 3 ? from[2] : 0.5) * (maxPosZ - minPosZ) : 0;
|
|
9940
10149
|
} else if (fromCenter) {
|
|
9941
10150
|
fX = (minPosX + maxPosX) / 2;
|
|
9942
10151
|
fY = (minPosY + maxPosY) / 2;
|
|
10152
|
+
fZ = (minPosZ + maxPosZ) / 2;
|
|
9943
10153
|
} else if (fromLast) {
|
|
9944
10154
|
fX = pxArr[total - 1];
|
|
9945
10155
|
fY = pyArr[total - 1];
|
|
10156
|
+
fZ = pzArr[total - 1];
|
|
9946
10157
|
} else if (isNum(from)) {
|
|
9947
10158
|
fX = pxArr[from];
|
|
9948
10159
|
fY = pyArr[from];
|
|
10160
|
+
fZ = pzArr[from];
|
|
9949
10161
|
}
|
|
9950
10162
|
for (let index = 0; index < total; index++) {
|
|
9951
10163
|
const distanceX = fX - pxArr[index];
|
|
9952
10164
|
const distanceY = fY - pyArr[index];
|
|
9953
|
-
|
|
10165
|
+
const distanceZ = fZ - pzArr[index];
|
|
10166
|
+
let value = sqrt(distanceX * distanceX + distanceY * distanceY + (has3D ? distanceZ * distanceZ : 0));
|
|
9954
10167
|
if (axis === 'x') value = -distanceX;
|
|
9955
10168
|
if (axis === 'y') value = -distanceY;
|
|
10169
|
+
if (axis === 'z') value = -distanceZ;
|
|
9956
10170
|
values.push(value);
|
|
9957
10171
|
}
|
|
9958
10172
|
let minDist = Infinity;
|
|
9959
|
-
for (let index = 0
|
|
10173
|
+
for (let index = 0; index < total; index++) {
|
|
9960
10174
|
const absVal = abs(values[index]);
|
|
9961
10175
|
if (absVal > 0 && absVal < minDist) minDist = absVal;
|
|
9962
10176
|
}
|
|
9963
10177
|
if (minDist > 0 && minDist < Infinity) {
|
|
9964
|
-
for (let index = 0
|
|
10178
|
+
for (let index = 0; index < total; index++) {
|
|
9965
10179
|
values[index] = values[index] / minDist;
|
|
9966
10180
|
}
|
|
9967
10181
|
}
|
|
@@ -9975,32 +10189,51 @@
|
|
|
9975
10189
|
if (!grid) {
|
|
9976
10190
|
values.push(abs(fromIndex - index));
|
|
9977
10191
|
} else {
|
|
9978
|
-
|
|
10192
|
+
const dims = grid.length;
|
|
10193
|
+
const wh = grid[0] * grid[1];
|
|
10194
|
+
let fromX, fromY, fromZ;
|
|
9979
10195
|
if (fromArr) {
|
|
9980
10196
|
fromX = from[0] * (grid[0] - 1);
|
|
9981
10197
|
fromY = from[1] * (grid[1] - 1);
|
|
10198
|
+
fromZ = dims === 3 ? (from.length >= 3 ? from[2] : 0.5) * (grid[2] - 1) : 0;
|
|
9982
10199
|
} else if (fromCenter) {
|
|
9983
10200
|
fromX = (grid[0] - 1) / 2;
|
|
9984
10201
|
fromY = (grid[1] - 1) / 2;
|
|
10202
|
+
fromZ = dims === 3 ? (grid[2] - 1) / 2 : 0;
|
|
9985
10203
|
} else {
|
|
9986
10204
|
fromX = fromIndex % grid[0];
|
|
9987
|
-
fromY = floor(fromIndex / grid[0]);
|
|
10205
|
+
fromY = floor(fromIndex / grid[0]) % grid[1];
|
|
10206
|
+
fromZ = dims === 3 ? floor(fromIndex / wh) : 0;
|
|
9988
10207
|
}
|
|
9989
10208
|
const toX = index % grid[0];
|
|
9990
|
-
const toY = floor(index / grid[0]);
|
|
10209
|
+
const toY = floor(index / grid[0]) % grid[1];
|
|
10210
|
+
const toZ = dims === 3 ? floor(index / wh) : 0;
|
|
9991
10211
|
const distanceX = fromX - toX;
|
|
9992
10212
|
const distanceY = fromY - toY;
|
|
9993
|
-
|
|
10213
|
+
const distanceZ = fromZ - toZ;
|
|
10214
|
+
let value = sqrt(distanceX * distanceX + distanceY * distanceY + (dims === 3 ? distanceZ * distanceZ : 0));
|
|
9994
10215
|
if (axis === 'x') value = -distanceX;
|
|
9995
10216
|
if (axis === 'y') value = -distanceY;
|
|
10217
|
+
if (axis === 'z') value = -distanceZ;
|
|
9996
10218
|
values.push(value);
|
|
9997
10219
|
}
|
|
9998
10220
|
}
|
|
9999
10221
|
}
|
|
10000
|
-
maxValue =
|
|
10001
|
-
|
|
10002
|
-
if (
|
|
10003
|
-
|
|
10222
|
+
maxValue = values[0];
|
|
10223
|
+
for (let k = 1; k < total; k++) if (values[k] > maxValue) maxValue = values[k];
|
|
10224
|
+
if (staggerEase || reversed) {
|
|
10225
|
+
for (let k = 0; k < total; k++) {
|
|
10226
|
+
let v = values[k];
|
|
10227
|
+
if (staggerEase) v = staggerEase(v / maxValue) * maxValue;
|
|
10228
|
+
if (reversed) v = axis ? -v : abs(maxValue - v);
|
|
10229
|
+
values[k] = v;
|
|
10230
|
+
}
|
|
10231
|
+
}
|
|
10232
|
+
if (hasJitter) {
|
|
10233
|
+
jitterSamples = new Array(total);
|
|
10234
|
+
for (let k = 0; k < total; k++) jitterSamples[k] = rng(-1, 1, 4);
|
|
10235
|
+
}
|
|
10236
|
+
if (fromRandom) values = shuffle(values, rng);
|
|
10004
10237
|
}
|
|
10005
10238
|
const spacing = isRange ? (val2 - val1) / maxValue : val1;
|
|
10006
10239
|
if (isUnd(cachedOffset)) {
|
|
@@ -10008,6 +10241,11 @@
|
|
|
10008
10241
|
}
|
|
10009
10242
|
/** @type {String|Number} */
|
|
10010
10243
|
let output = cachedOffset + ((spacing * round$1(values[staggerIndex], 2)) || 0);
|
|
10244
|
+
if (hasJitter) {
|
|
10245
|
+
const progress = maxValue ? values[staggerIndex] / maxValue : 0;
|
|
10246
|
+
const mag = jitterStart + (jitterEnd - jitterStart) * progress;
|
|
10247
|
+
output = /** @type {Number} */(output) + jitterSamples[staggerIndex] * mag;
|
|
10248
|
+
}
|
|
10011
10249
|
if (params.modifier) output = params.modifier(/** @type {Number} */(output));
|
|
10012
10250
|
if (unitMatch) output = `${output}${unitMatch[2]}`;
|
|
10013
10251
|
return output;
|
|
@@ -10377,6 +10615,7 @@
|
|
|
10377
10615
|
*/
|
|
10378
10616
|
const generateTemplate = (type, params = {}) => {
|
|
10379
10617
|
let template = ``;
|
|
10618
|
+
if (!params) params = {};
|
|
10380
10619
|
const classString = isStr(params.class) ? ` class="${params.class}"` : '';
|
|
10381
10620
|
const cloneType = setValue(params.clone, false);
|
|
10382
10621
|
const wrapType = setValue(params.wrap, false);
|
|
@@ -10758,6 +10997,16 @@
|
|
|
10758
10997
|
|
|
10759
10998
|
|
|
10760
10999
|
|
|
11000
|
+
/**
|
|
11001
|
+
* @typedef {Object} ScrambleTextTween
|
|
11002
|
+
* @property {Number} from
|
|
11003
|
+
* @property {Number} to
|
|
11004
|
+
* @property {Number} duration
|
|
11005
|
+
* @property {Number} delay
|
|
11006
|
+
* @property {String} ease
|
|
11007
|
+
* @property {(v: Number) => String} modifier
|
|
11008
|
+
*/
|
|
11009
|
+
|
|
10761
11010
|
/**
|
|
10762
11011
|
* '-' is the range operator; place it at the start or end of the string to use it as a literal (e.g. '-abc' or 'abc-')
|
|
10763
11012
|
* @param {String} str
|
|
@@ -10795,7 +11044,7 @@
|
|
|
10795
11044
|
* progressively revealing the original text.
|
|
10796
11045
|
*
|
|
10797
11046
|
* @param {ScrambleTextParams} [params]
|
|
10798
|
-
* @return {FunctionValue}
|
|
11047
|
+
* @return {FunctionValue<ScrambleTextTween>}
|
|
10799
11048
|
*/
|
|
10800
11049
|
const scrambleText = (params = {}) => {
|
|
10801
11050
|
if (!params) params = {};
|