animejs 4.4.0 → 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 +4 -5
- package/dist/bundles/anime.esm.js +491 -272
- package/dist/bundles/anime.esm.min.js +2 -2
- package/dist/bundles/anime.umd.js +491 -272
- 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 +93 -73
- package/dist/modules/core/render.js +96 -76
- 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 - ESM 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
|
|
@@ -725,6 +744,11 @@ const maxFps = 240;
|
|
|
725
744
|
const emptyString = '';
|
|
726
745
|
const cssVarPrefix = 'var(';
|
|
727
746
|
|
|
747
|
+
// Arrays
|
|
748
|
+
|
|
749
|
+
// 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.
|
|
750
|
+
const emptyArray = [];
|
|
751
|
+
|
|
728
752
|
const shortTransforms = /*#__PURE__*/ (() => {
|
|
729
753
|
const map = new Map();
|
|
730
754
|
map.set('x', 'translateX');
|
|
@@ -758,6 +782,13 @@ const transformsFragmentStrings = /*#__PURE__*/ validTransforms.reduce((a, v) =>
|
|
|
758
782
|
/** @return {void} */
|
|
759
783
|
const noop = () => {};
|
|
760
784
|
|
|
785
|
+
/**
|
|
786
|
+
* @template T
|
|
787
|
+
* @param {T} v
|
|
788
|
+
* @return {T}
|
|
789
|
+
*/
|
|
790
|
+
const noopModifier = v => v;
|
|
791
|
+
|
|
761
792
|
// Regex
|
|
762
793
|
|
|
763
794
|
const validRgbHslRgx = /\)\s*[-.\d]/;
|
|
@@ -779,10 +810,13 @@ const cssVariableMatchRgx = /var\(\s*(--[\w-]+)(?:\s*,\s*([^)]+))?\s*\)/;
|
|
|
779
810
|
/**
|
|
780
811
|
* @typedef {Object} EditorGlobals
|
|
781
812
|
* @property {boolean} showPanel
|
|
782
|
-
* @property {boolean} synced
|
|
783
813
|
* @property {Function} addAnimation
|
|
814
|
+
* @property {Function} addSet
|
|
784
815
|
* @property {Function} addTimeline
|
|
785
816
|
* @property {Function} addTimelineChild
|
|
817
|
+
* @property {Function} addTimelineLabel
|
|
818
|
+
* @property {Function} addTimelineCall
|
|
819
|
+
* @property {Function} addTimelineSync
|
|
786
820
|
* @property {Function} resolveStagger
|
|
787
821
|
* @property {Object|null} _head
|
|
788
822
|
* @property {Object|null} _tail
|
|
@@ -805,7 +839,7 @@ const defaults = {
|
|
|
805
839
|
loopDelay: 0,
|
|
806
840
|
ease: 'out(2)',
|
|
807
841
|
composition: compositionTypes.replace,
|
|
808
|
-
modifier:
|
|
842
|
+
modifier: noopModifier,
|
|
809
843
|
onBegin: noop,
|
|
810
844
|
onBeforeUpdate: noop,
|
|
811
845
|
onUpdate: noop,
|
|
@@ -835,7 +869,7 @@ const globals = {
|
|
|
835
869
|
editor: null,
|
|
836
870
|
};
|
|
837
871
|
|
|
838
|
-
const globalVersions = { version: '4.
|
|
872
|
+
const globalVersions = { version: '4.5.0', engine: null };
|
|
839
873
|
|
|
840
874
|
if (isBrowser) {
|
|
841
875
|
if (!win.AnimeJS) win.AnimeJS = [];
|
|
@@ -982,7 +1016,7 @@ const snap$1 = (v, increment) => isArr(increment) ? increment.reduce((closest, c
|
|
|
982
1016
|
* @param {Number} factor - Interpolation factor in the range [0, 1]
|
|
983
1017
|
* @return {Number} The interpolated value
|
|
984
1018
|
*/
|
|
985
|
-
const lerp$1 = (start, end, factor) => start + (end - start) * factor;
|
|
1019
|
+
const lerp$1 = (start, end, factor) => factor === 1 ? end : factor === 0 ? start : start + (end - start) * factor;
|
|
986
1020
|
|
|
987
1021
|
/**
|
|
988
1022
|
* Replaces infinity with maximum safe value
|
|
@@ -1231,6 +1265,61 @@ const buildTransformString = (props) => {
|
|
|
1231
1265
|
return str;
|
|
1232
1266
|
};
|
|
1233
1267
|
|
|
1268
|
+
/**
|
|
1269
|
+
* 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.
|
|
1270
|
+
*
|
|
1271
|
+
* import { registerAdapter } from 'animejs/adapters';
|
|
1272
|
+
*
|
|
1273
|
+
* const myAdapter = registerAdapter();
|
|
1274
|
+
* const widget = myAdapter.registerTargetAdapter((t) => t instanceof MyWidget);
|
|
1275
|
+
* widget.registerProperty('value',
|
|
1276
|
+
* (t) => t.getValue(),
|
|
1277
|
+
* (target, value) => target.setValue(value),
|
|
1278
|
+
* );
|
|
1279
|
+
*
|
|
1280
|
+
* 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.
|
|
1281
|
+
*
|
|
1282
|
+
* 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.
|
|
1283
|
+
*/
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
const adapters = /** @type {Adapter[]} */([]);
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Internal resolution. Tries every Adapter's target adapters first (in registration order, first match wins), then every Adapter's property resolvers.
|
|
1290
|
+
*
|
|
1291
|
+
* @param {any} target
|
|
1292
|
+
* @param {string} name
|
|
1293
|
+
* @return {TargetAdapterEntry | null}
|
|
1294
|
+
*/
|
|
1295
|
+
function resolveAdapterEntry(target, name) {
|
|
1296
|
+
if (!target) return null;
|
|
1297
|
+
const al = adapters.length;
|
|
1298
|
+
outer: for (let i = 0; i < al; i++) {
|
|
1299
|
+
const a = adapters[i];
|
|
1300
|
+
if (a.detect && !a.detect(target)) continue;
|
|
1301
|
+
const tas = a.targetAdapters;
|
|
1302
|
+
for (let j = 0, m = tas.length; j < m; j++) {
|
|
1303
|
+
const ta = tas[j];
|
|
1304
|
+
if (ta.detect(target)) {
|
|
1305
|
+
const entry = ta.props[name];
|
|
1306
|
+
if (entry && (!entry.gate || entry.gate(target))) return entry;
|
|
1307
|
+
break outer;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
for (let i = 0; i < al; i++) {
|
|
1312
|
+
const a = adapters[i];
|
|
1313
|
+
if (a.detect && !a.detect(target)) continue;
|
|
1314
|
+
const rs = a.propertyResolvers;
|
|
1315
|
+
for (let j = 0, m = rs.length; j < m; j++) {
|
|
1316
|
+
const entry = rs[j](target, name);
|
|
1317
|
+
if (entry) return entry;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
return null;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1234
1323
|
|
|
1235
1324
|
|
|
1236
1325
|
/**
|
|
@@ -1328,6 +1417,21 @@ const setValue = (targetValue, defaultValue) => {
|
|
|
1328
1417
|
return isUnd(targetValue) ? defaultValue : targetValue;
|
|
1329
1418
|
};
|
|
1330
1419
|
|
|
1420
|
+
/**
|
|
1421
|
+
* 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.
|
|
1422
|
+
*
|
|
1423
|
+
* @param {String} value
|
|
1424
|
+
* @param {Target} target
|
|
1425
|
+
* @return {String|Number}
|
|
1426
|
+
*/
|
|
1427
|
+
const resolveCssVar = (value, target) => {
|
|
1428
|
+
const match = value.match(cssVariableMatchRgx);
|
|
1429
|
+
const el = target[isDomSymbol] ? target : document.documentElement;
|
|
1430
|
+
let computed = getComputedStyle(/** @type {HTMLElement} */(el))?.getPropertyValue(match[1]);
|
|
1431
|
+
if ((!computed || computed.trim() === emptyString) && match[2]) computed = match[2].trim();
|
|
1432
|
+
return computed || 0;
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1331
1435
|
/**
|
|
1332
1436
|
* @param {TweenPropValue} value
|
|
1333
1437
|
* @param {Target} target
|
|
@@ -1338,30 +1442,26 @@ const setValue = (targetValue, defaultValue) => {
|
|
|
1338
1442
|
* @return {any}
|
|
1339
1443
|
*/
|
|
1340
1444
|
const getFunctionValue = (value, target, index, targets, store, prevTween) => {
|
|
1341
|
-
let func;
|
|
1342
1445
|
if (isFnc(value)) {
|
|
1343
|
-
|
|
1446
|
+
if (!store) {
|
|
1447
|
+
const computed = /** @type {Function} */(value)(target, index, targets, prevTween);
|
|
1448
|
+
// Fallback to 0 if the function returns undefined, NaN, null, false or 0
|
|
1449
|
+
return !isNaN(+computed) ? +computed : computed || 0;
|
|
1450
|
+
}
|
|
1451
|
+
const func = () => {
|
|
1344
1452
|
const computed = /** @type {Function} */(value)(target, index, targets, prevTween);
|
|
1345
|
-
// Fallback to 0 if the function returns undefined / NaN / null / false / 0
|
|
1346
1453
|
return !isNaN(+computed) ? +computed : computed || 0;
|
|
1347
1454
|
};
|
|
1348
|
-
|
|
1349
|
-
func
|
|
1350
|
-
const match = value.match(cssVariableMatchRgx);
|
|
1351
|
-
const cssVarName = match[1];
|
|
1352
|
-
const fallbackValue = match[2];
|
|
1353
|
-
let computed = getComputedStyle(/** @type {HTMLElement} */(target))?.getPropertyValue(cssVarName);
|
|
1354
|
-
// Use fallback if CSS variable is not set or empty
|
|
1355
|
-
if ((!computed || computed.trim() === emptyString) && fallbackValue) {
|
|
1356
|
-
computed = fallbackValue.trim();
|
|
1357
|
-
}
|
|
1358
|
-
return computed || 0;
|
|
1359
|
-
};
|
|
1360
|
-
} else {
|
|
1361
|
-
return value;
|
|
1455
|
+
store.func = func;
|
|
1456
|
+
return func();
|
|
1362
1457
|
}
|
|
1363
|
-
if (
|
|
1364
|
-
|
|
1458
|
+
if (isStr(value) && stringStartsWith(value, cssVarPrefix)) {
|
|
1459
|
+
if (!store) return resolveCssVar(/** @type {String} */(value), target);
|
|
1460
|
+
const func = () => resolveCssVar(/** @type {String} */(value), target);
|
|
1461
|
+
store.func = func;
|
|
1462
|
+
return func();
|
|
1463
|
+
}
|
|
1464
|
+
return value;
|
|
1365
1465
|
};
|
|
1366
1466
|
|
|
1367
1467
|
/**
|
|
@@ -1408,6 +1508,12 @@ const getCSSValue = (target, propName, animationInlineStyles) => {
|
|
|
1408
1508
|
*/
|
|
1409
1509
|
const getOriginalAnimatableValue = (target, propName, tweenType, animationInlineStyles) => {
|
|
1410
1510
|
const type = !isUnd(tweenType) ? tweenType : getTweenType(target, propName);
|
|
1511
|
+
const adapterProp = resolveAdapterEntry(target, propName);
|
|
1512
|
+
if (adapterProp) {
|
|
1513
|
+
const value = adapterProp.get(target);
|
|
1514
|
+
if (value && animationInlineStyles) animationInlineStyles[propName] = value;
|
|
1515
|
+
return value == null ? 0 : value;
|
|
1516
|
+
}
|
|
1411
1517
|
if (type === tweenTypes.OBJECT) {
|
|
1412
1518
|
const value = target[propName];
|
|
1413
1519
|
if (value && animationInlineStyles) animationInlineStyles[propName] = value;
|
|
@@ -1449,7 +1555,7 @@ const createDecomposedValueTargetObject = () => {
|
|
|
1449
1555
|
};
|
|
1450
1556
|
|
|
1451
1557
|
/**
|
|
1452
|
-
* @param {String|Number} rawValue
|
|
1558
|
+
* @param {String|Number|Object} rawValue
|
|
1453
1559
|
* @param {TweenDecomposedValue} targetObject
|
|
1454
1560
|
* @return {TweenDecomposedValue}
|
|
1455
1561
|
*/
|
|
@@ -1467,39 +1573,38 @@ const decomposeRawValue = (rawValue, targetObject) => {
|
|
|
1467
1573
|
// It's a number
|
|
1468
1574
|
targetObject.n = num;
|
|
1469
1575
|
return targetObject;
|
|
1576
|
+
}
|
|
1577
|
+
// let str = /** @type {String} */(rawValue).trim();
|
|
1578
|
+
let str = /** @type {String} */(rawValue);
|
|
1579
|
+
// Parsing operators (+=, -=, *=) manually is much faster than using regex here
|
|
1580
|
+
if (str[1] === '=') {
|
|
1581
|
+
targetObject.o = str[0];
|
|
1582
|
+
str = str.slice(2);
|
|
1583
|
+
}
|
|
1584
|
+
// Skip exec regex if the value type is complex or color to avoid long regex backtracking
|
|
1585
|
+
const unitMatch = str.includes(' ') ? false : unitsExecRgx.exec(str);
|
|
1586
|
+
if (unitMatch) {
|
|
1587
|
+
// Has a number and a unit
|
|
1588
|
+
targetObject.t = valueTypes.UNIT;
|
|
1589
|
+
targetObject.n = +unitMatch[1];
|
|
1590
|
+
targetObject.u = unitMatch[2];
|
|
1591
|
+
return targetObject;
|
|
1592
|
+
} else if (targetObject.o) {
|
|
1593
|
+
// Has an operator (+=, -=, *=)
|
|
1594
|
+
targetObject.n = +str;
|
|
1595
|
+
return targetObject;
|
|
1596
|
+
} else if (isCol(str)) {
|
|
1597
|
+
// Color string
|
|
1598
|
+
targetObject.t = valueTypes.COLOR;
|
|
1599
|
+
targetObject.d = convertColorStringValuesToRgbaArray(str);
|
|
1600
|
+
return targetObject;
|
|
1470
1601
|
} else {
|
|
1471
|
-
//
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
}
|
|
1478
|
-
// Skip exec regex if the value type is complex or color to avoid long regex backtracking
|
|
1479
|
-
const unitMatch = str.includes(' ') ? false : unitsExecRgx.exec(str);
|
|
1480
|
-
if (unitMatch) {
|
|
1481
|
-
// Has a number and a unit
|
|
1482
|
-
targetObject.t = valueTypes.UNIT;
|
|
1483
|
-
targetObject.n = +unitMatch[1];
|
|
1484
|
-
targetObject.u = unitMatch[2];
|
|
1485
|
-
return targetObject;
|
|
1486
|
-
} else if (targetObject.o) {
|
|
1487
|
-
// Has an operator (+=, -=, *=)
|
|
1488
|
-
targetObject.n = +str;
|
|
1489
|
-
return targetObject;
|
|
1490
|
-
} else if (isCol(str)) {
|
|
1491
|
-
// Is a color
|
|
1492
|
-
targetObject.t = valueTypes.COLOR;
|
|
1493
|
-
targetObject.d = convertColorStringValuesToRgbaArray(str);
|
|
1494
|
-
return targetObject;
|
|
1495
|
-
} else {
|
|
1496
|
-
// Is a more complex string (generally svg coords, calc() or filters CSS values)
|
|
1497
|
-
const matchedNumbers = str.match(digitWithExponentRgx);
|
|
1498
|
-
targetObject.t = valueTypes.COMPLEX;
|
|
1499
|
-
targetObject.d = matchedNumbers ? matchedNumbers.map(Number) : [];
|
|
1500
|
-
targetObject.s = str.split(digitWithExponentRgx) || [];
|
|
1501
|
-
return targetObject;
|
|
1502
|
-
}
|
|
1602
|
+
// Is a more complex string (generally svg coords, calc() or filters CSS values)
|
|
1603
|
+
const matchedNumbers = str.match(digitWithExponentRgx);
|
|
1604
|
+
targetObject.t = valueTypes.COMPLEX;
|
|
1605
|
+
targetObject.d = matchedNumbers ? matchedNumbers.map(Number) : [];
|
|
1606
|
+
targetObject.s = str.split(digitWithExponentRgx) || [];
|
|
1607
|
+
return targetObject;
|
|
1503
1608
|
}
|
|
1504
1609
|
};
|
|
1505
1610
|
|
|
@@ -1520,30 +1625,6 @@ const decomposeTweenValue = (tween, targetObject) => {
|
|
|
1520
1625
|
|
|
1521
1626
|
const decomposedOriginalValue = createDecomposedValueTargetObject();
|
|
1522
1627
|
|
|
1523
|
-
/**
|
|
1524
|
-
* @param {Tween} tween
|
|
1525
|
-
* @param {Number} progress
|
|
1526
|
-
* @param {Number} precision
|
|
1527
|
-
* @return {String}
|
|
1528
|
-
*/
|
|
1529
|
-
const composeColorValue = (tween, progress, precision) => {
|
|
1530
|
-
const mod = tween._modifier;
|
|
1531
|
-
const fn = tween._fromNumbers;
|
|
1532
|
-
const tn = tween._toNumbers;
|
|
1533
|
-
const r = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[0], tn[0], progress))), 0, 255), 0);
|
|
1534
|
-
const g = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[1], tn[1], progress))), 0, 255), 0);
|
|
1535
|
-
const b = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[2], tn[2], progress))), 0, 255), 0);
|
|
1536
|
-
const a = clamp$1(/** @type {Number} */(mod(round$1(lerp$1(fn[3], tn[3], progress), precision))), 0, 1);
|
|
1537
|
-
if (tween._composition !== compositionTypes.none) {
|
|
1538
|
-
const ns = tween._numbers;
|
|
1539
|
-
ns[0] = r;
|
|
1540
|
-
ns[1] = g;
|
|
1541
|
-
ns[2] = b;
|
|
1542
|
-
ns[3] = a;
|
|
1543
|
-
}
|
|
1544
|
-
return `rgba(${r},${g},${b},${a})`;
|
|
1545
|
-
};
|
|
1546
|
-
|
|
1547
1628
|
/**
|
|
1548
1629
|
* @param {Tween} tween
|
|
1549
1630
|
* @param {Number} progress
|
|
@@ -1555,15 +1636,14 @@ const composeComplexValue = (tween, progress, precision) => {
|
|
|
1555
1636
|
const fn = tween._fromNumbers;
|
|
1556
1637
|
const tn = tween._toNumbers;
|
|
1557
1638
|
const ts = tween._strings;
|
|
1558
|
-
const hasComposition = tween._composition !== compositionTypes.none;
|
|
1559
1639
|
let v = ts[0];
|
|
1560
1640
|
for (let j = 0, l = tn.length; j < l; j++) {
|
|
1561
1641
|
const n = /** @type {Number} */(mod(round$1(lerp$1(fn[j], tn[j], progress), precision)));
|
|
1562
1642
|
const s = ts[j + 1];
|
|
1563
1643
|
v += `${s ? n + s : n}`;
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1644
|
+
// 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.
|
|
1645
|
+
// Potential optimization, skip the write when nothing reads it: if (hasComposition || tween._setter) tween._numbers[j] = n;
|
|
1646
|
+
tween._numbers[j] = n;
|
|
1567
1647
|
}
|
|
1568
1648
|
return v;
|
|
1569
1649
|
};
|
|
@@ -1615,12 +1695,14 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1615
1695
|
// Execute the "expensive" iterations calculations only when necessary
|
|
1616
1696
|
if (iterationCount > 1) {
|
|
1617
1697
|
// bitwise NOT operator seems to be generally faster than Math.floor() across browsers
|
|
1618
|
-
const
|
|
1698
|
+
const period = iterationDuration + (isCurrentTimeEqualOrAboveDuration ? 0 : _loopDelay);
|
|
1699
|
+
const currentIteration = ~~(tickableCurrentTime / period);
|
|
1619
1700
|
tickable._currentIteration = clamp$1(currentIteration, 0, iterationCount);
|
|
1620
1701
|
// Prevent the iteration count to go above the max iterations when reaching the end of the animation
|
|
1621
1702
|
if (isCurrentTimeEqualOrAboveDuration) tickable._currentIteration--;
|
|
1622
1703
|
isOdd = tickable._currentIteration % 2;
|
|
1623
|
-
|
|
1704
|
+
// 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.
|
|
1705
|
+
iterationElapsedTime = tickableCurrentTime - currentIteration * period || 0;
|
|
1624
1706
|
}
|
|
1625
1707
|
|
|
1626
1708
|
// Checks if exactly one of _reversed and (_alternate && isOdd) is true
|
|
@@ -1652,12 +1734,14 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1652
1734
|
if (
|
|
1653
1735
|
forcedTick ||
|
|
1654
1736
|
tickMode === tickModes.AUTO && (
|
|
1655
|
-
|
|
1737
|
+
// Timeline children render from their offset instead of their delay so the gap left by a truncated sibling is covered on seek.
|
|
1738
|
+
time >= (parent && tickableDelay > 0 ? 0 : tickableDelay) && time <= tickableEndTime || // Normal render
|
|
1656
1739
|
time <= tickableDelay && tickablePrevTime > tickableDelay || // Playhead is before the animation start time so make sure the animation is at its initial state
|
|
1657
1740
|
time >= tickableEndTime && tickablePrevTime !== duration // Playhead is after the animation end time so make sure the animation is at its end state
|
|
1658
1741
|
) ||
|
|
1659
1742
|
iterationTime >= tickableEndTime && tickablePrevTime !== duration ||
|
|
1660
|
-
iterationTime
|
|
1743
|
+
// 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.
|
|
1744
|
+
iterationTime <= tickableDelay && tickablePrevTime > 0 && !isCurrentTimeEqualOrAboveDuration ||
|
|
1661
1745
|
time <= tickablePrevTime && tickablePrevTime === duration && completed || // Force a render if a seek occurs on an completed animation
|
|
1662
1746
|
isCurrentTimeEqualOrAboveDuration && !completed && isSetter // This prevents 0 duration tickables to be skipped
|
|
1663
1747
|
) {
|
|
@@ -1673,7 +1757,8 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1673
1757
|
|
|
1674
1758
|
// Time has jumped more than globals.tickThreshold so consider this tick manual
|
|
1675
1759
|
const forcedRender = forcedTick || (isRunningBackwards ? deltaTime * -1 : deltaTime) >= globals.tickThreshold;
|
|
1676
|
-
|
|
1760
|
+
// Round to match the precision of tween._absoluteStartTime so equal-time boundary checks compare cleanly without floating point drift from the unrounded _offset.
|
|
1761
|
+
const absoluteTime = round$1(tickable._offset + (parent ? parent._offset : 0) + tickableDelay + iterationTime, 12);
|
|
1677
1762
|
|
|
1678
1763
|
// Only Animation can have tweens, Timer returns undefined
|
|
1679
1764
|
let tween = /** @type {Tween} */(/** @type {JSAnimation} */(tickable)._head);
|
|
@@ -1692,15 +1777,38 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1692
1777
|
const tweenNextRep = tween._nextRep;
|
|
1693
1778
|
const tweenPrevRep = tween._prevRep;
|
|
1694
1779
|
const tweenHasComposition = tweenComposition !== compositionTypes.none;
|
|
1780
|
+
// The previous sibling stops writing at its truncated end, so this tween takes over the hold from that point.
|
|
1781
|
+
const tweenPrevRepEndTime = tweenPrevRep ? tweenPrevRep._absoluteStartTime + tweenPrevRep._changeDuration : 0;
|
|
1782
|
+
const tweenPrevRepIsCrossParent = tweenPrevRep && tweenPrevRep.parent !== tween.parent;
|
|
1783
|
+
// Same parent keyframes take over at their own start, end plus delay equals the next start by construction.
|
|
1784
|
+
// Cross parent siblings take over at their update start.
|
|
1785
|
+
// Negative delay siblings take over at their own start instead.
|
|
1786
|
+
const tweenNextRepTakeover = !tweenNextRep || tweenNextRep._isOverridden ? tweenAbsEndTime :
|
|
1787
|
+
tweenNextRep.parent === tween.parent ? tweenAbsEndTime + tweenNextRep._delay :
|
|
1788
|
+
tweenNextRep._absoluteStartTime < tweenNextRep._absoluteUpdateStartTime ? tweenNextRep._absoluteStartTime : tweenNextRep._absoluteUpdateStartTime;
|
|
1695
1789
|
|
|
1696
1790
|
if ((forcedRender || (
|
|
1697
|
-
|
|
1698
|
-
(tweenCurrentTime !==
|
|
1699
|
-
|
|
1791
|
+
// 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.
|
|
1792
|
+
(tweenCurrentTime !== tweenChangeDuration || absoluteTime <= tweenNextRepTakeover ||
|
|
1793
|
+
(tweenPrevRep && !tweenPrevRepIsCrossParent && (!tweenNextRep || tweenNextRep.parent !== tween.parent))) &&
|
|
1794
|
+
// A cross parent tween re-renders its from value from the previous sibling truncated end so the handoff gap holds.
|
|
1795
|
+
// 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.
|
|
1796
|
+
(tweenCurrentTime !== 0 || absoluteTime >= tween._absoluteStartTime ||
|
|
1797
|
+
(tweenPrevRepIsCrossParent && !tween._hasFromValue && !tweenPrevRep._isOverridden && absoluteTime >= tweenPrevRepEndTime) ||
|
|
1798
|
+
(tweenNextRep && !tweenNextRep._isOverridden && tweenNextRep.parent === tween.parent && tweenNextRep._currentTime !== 0 && iterationTime < tweenNextRep._startTime))
|
|
1799
|
+
)) &&
|
|
1800
|
+
// 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.
|
|
1801
|
+
(!tweenPrevRep || tweenPrevRepIsCrossParent || iterationTime >= tween._startTime) &&
|
|
1802
|
+
(!tweenHasComposition || (
|
|
1700
1803
|
!tween._isOverridden &&
|
|
1701
1804
|
(!tween._isOverlapped || absoluteTime <= tweenAbsEndTime) &&
|
|
1702
|
-
|
|
1703
|
-
(!
|
|
1805
|
+
// The next sibling owns the value past its takeover point, so yielding there keeps writes single owner in both directions.
|
|
1806
|
+
(!tweenNextRep || tweenNextRep._isOverridden || absoluteTime <= tweenNextRepTakeover) &&
|
|
1807
|
+
// The previous sibling owns the value up to its truncated end.
|
|
1808
|
+
// Cross parent tweens take over the hold from that point, explicit from values wait for their own start.
|
|
1809
|
+
(!tweenPrevRep || (tweenPrevRep._isOverridden || (!tweenPrevRepIsCrossParent ?
|
|
1810
|
+
absoluteTime >= tweenPrevRepEndTime + tween._delay :
|
|
1811
|
+
absoluteTime >= tween._absoluteStartTime || (!tween._hasFromValue && absoluteTime >= tweenPrevRepEndTime))))
|
|
1704
1812
|
))
|
|
1705
1813
|
) {
|
|
1706
1814
|
|
|
@@ -1711,7 +1819,7 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1711
1819
|
const tweenType = tween._tweenType;
|
|
1712
1820
|
const tweenIsObject = tweenType === tweenTypes.OBJECT;
|
|
1713
1821
|
const tweenIsNumber = tweenValueType === valueTypes.NUMBER;
|
|
1714
|
-
// Only round the in-between frames values if the final value is a string
|
|
1822
|
+
// 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.
|
|
1715
1823
|
const tweenPrecision = (tweenIsNumber && tweenIsObject) || tweenProgress === 0 || tweenProgress === 1 ? -1 : globals.precision;
|
|
1716
1824
|
|
|
1717
1825
|
// Recompose tween value
|
|
@@ -1727,7 +1835,22 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1727
1835
|
number = /** @type {Number} */(tweenModifier(round$1(lerp$1(tween._fromNumber, tween._toNumber, tweenProgress), tweenPrecision)));
|
|
1728
1836
|
value = `${number}${tween._unit}`;
|
|
1729
1837
|
} else if (tweenValueType === valueTypes.COLOR) {
|
|
1730
|
-
|
|
1838
|
+
const ns = tween._numbers;
|
|
1839
|
+
const fn = tween._fromNumbers;
|
|
1840
|
+
const tn = tween._toNumbers;
|
|
1841
|
+
const omt = 1 - tweenProgress;
|
|
1842
|
+
const fr = fn[0], fg = fn[1], fb = fn[2];
|
|
1843
|
+
const tr = tn[0], tg = tn[1], tb = tn[2];
|
|
1844
|
+
// RGB channels lerp in pseudo-linear space (square inputs, sqrt result) to approximate gamma-correct blending.
|
|
1845
|
+
// See https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear.
|
|
1846
|
+
ns[0] = /** @type {Number} */(tweenModifier(Math.sqrt(fr * fr * omt + tr * tr * tweenProgress)));
|
|
1847
|
+
ns[1] = /** @type {Number} */(tweenModifier(Math.sqrt(fg * fg * omt + tg * tg * tweenProgress)));
|
|
1848
|
+
ns[2] = /** @type {Number} */(tweenModifier(Math.sqrt(fb * fb * omt + tb * tb * tweenProgress)));
|
|
1849
|
+
ns[3] = /** @type {Number} */(tweenModifier(lerp$1(fn[3], tn[3], tweenProgress)));
|
|
1850
|
+
// The rgba string is built only for the dispatch path or the internalRender composition tick (setters handles the color comp)
|
|
1851
|
+
if (!tween._setter || internalRender) {
|
|
1852
|
+
value = `rgba(${round$1(ns[0], 0)},${round$1(ns[1], 0)},${round$1(ns[2], 0)},${ns[3]})`;
|
|
1853
|
+
}
|
|
1731
1854
|
} else if (tweenValueType === valueTypes.COMPLEX) {
|
|
1732
1855
|
value = composeComplexValue(tween, tweenProgress, tweenPrecision);
|
|
1733
1856
|
}
|
|
@@ -1742,7 +1865,9 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1742
1865
|
const tweenProperty = tween.property;
|
|
1743
1866
|
tweenTarget = tween.target;
|
|
1744
1867
|
|
|
1745
|
-
if (
|
|
1868
|
+
if (tween._setter) {
|
|
1869
|
+
tween._setter(tweenTarget, number, tween);
|
|
1870
|
+
} else if (tweenIsObject) {
|
|
1746
1871
|
tweenTarget[tweenProperty] = value;
|
|
1747
1872
|
} else if (tweenType === tweenTypes.ATTRIBUTE) {
|
|
1748
1873
|
/** @type {DOMTarget} */(tweenTarget).setAttribute(tweenProperty, /** @type {String} */(value));
|
|
@@ -1770,6 +1895,9 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1770
1895
|
tween._value = value;
|
|
1771
1896
|
}
|
|
1772
1897
|
|
|
1898
|
+
} else if (tweenCurrentTime && tweenPrevRep && !tweenPrevRepIsCrossParent && iterationTime < tween._startTime) {
|
|
1899
|
+
// Mark the keyframe as reverted when the playhead moves before its start, the previous keyframe owns the from revert and writes it once.
|
|
1900
|
+
tween._currentTime = 0;
|
|
1773
1901
|
}
|
|
1774
1902
|
|
|
1775
1903
|
if (tweenTransformsNeedUpdate && tween._renderTransforms) {
|
|
@@ -1830,50 +1958,6 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1830
1958
|
return hasRendered;
|
|
1831
1959
|
};
|
|
1832
1960
|
|
|
1833
|
-
// Shared context for extracted forEachChildren callbacks in tick()
|
|
1834
|
-
// Avoids closure allocation every frame
|
|
1835
|
-
|
|
1836
|
-
let renderCtxChildrenTime = 0;
|
|
1837
|
-
let renderCtxTlFps = 0;
|
|
1838
|
-
let renderCtxTickTime = 0;
|
|
1839
|
-
let renderCtxTickMode = 0;
|
|
1840
|
-
let renderCtxMuteCallbacks = 0;
|
|
1841
|
-
let renderCtxInternalRender = 0;
|
|
1842
|
-
let renderCtxChildrenHasRendered = 0;
|
|
1843
|
-
let renderCtxChildrenHaveCompleted = true;
|
|
1844
|
-
let loopCtxIsRunningBackwards = false;
|
|
1845
|
-
let loopCtxIterationDuration = 0;
|
|
1846
|
-
let loopCtxMuteCallbacks = 0;
|
|
1847
|
-
|
|
1848
|
-
/** @param {JSAnimation} child */
|
|
1849
|
-
const tickLoopChild = (child) => {
|
|
1850
|
-
if (!loopCtxIsRunningBackwards) {
|
|
1851
|
-
// Force an internal render to trigger the callbacks if the child has not completed on loop
|
|
1852
|
-
if (!child.completed && !child.backwards && child._currentTime < child.iterationDuration) {
|
|
1853
|
-
render(child, loopCtxIterationDuration, loopCtxMuteCallbacks, 1, tickModes.FORCE);
|
|
1854
|
-
}
|
|
1855
|
-
// Reset their began and completed flags to allow retrigering callbacks on the next iteration
|
|
1856
|
-
child.began = false;
|
|
1857
|
-
child.completed = false;
|
|
1858
|
-
} else {
|
|
1859
|
-
const childDuration = child.duration;
|
|
1860
|
-
const childStartTime = child._offset + child._delay;
|
|
1861
|
-
const childEndTime = childStartTime + childDuration;
|
|
1862
|
-
// Triggers the onComplete callback on reverse for children on the edges of the timeline
|
|
1863
|
-
if (!loopCtxMuteCallbacks && childDuration <= minValue && (!childStartTime || childEndTime === loopCtxIterationDuration)) {
|
|
1864
|
-
child.onComplete(child);
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
};
|
|
1868
|
-
|
|
1869
|
-
/** @param {JSAnimation} child */
|
|
1870
|
-
const tickRenderChild = (child) => {
|
|
1871
|
-
const childTime = round$1((renderCtxChildrenTime - child._offset) * child._speed, 12); // Rounding is needed when using seconds
|
|
1872
|
-
const childTickMode = child._fps < renderCtxTlFps ? child.requestTick(renderCtxTickTime) : renderCtxTickMode;
|
|
1873
|
-
renderCtxChildrenHasRendered += render(child, childTime, renderCtxMuteCallbacks, renderCtxInternalRender, childTickMode);
|
|
1874
|
-
if (!child.completed && renderCtxChildrenHaveCompleted) renderCtxChildrenHaveCompleted = false;
|
|
1875
|
-
};
|
|
1876
|
-
|
|
1877
1961
|
/**
|
|
1878
1962
|
* @param {Tickable} tickable
|
|
1879
1963
|
* @param {Number} time
|
|
@@ -1890,28 +1974,44 @@ const tick = (tickable, time, muteCallbacks, internalRender, tickMode) => {
|
|
|
1890
1974
|
const tlIsRunningBackwards = tl.backwards;
|
|
1891
1975
|
const tlChildrenTime = internalRender ? time : tl._iterationTime;
|
|
1892
1976
|
const tlCildrenTickTime = now();
|
|
1977
|
+
|
|
1893
1978
|
let tlChildrenHasRendered = 0;
|
|
1894
1979
|
let tlChildrenHaveCompleted = true;
|
|
1980
|
+
|
|
1895
1981
|
// If the timeline has looped forward, we need to manually triggers children skipped callbacks
|
|
1896
1982
|
if (!internalRender && tl._currentIteration !== _currentIteration) {
|
|
1897
1983
|
const tlIterationDuration = tl.iterationDuration;
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1984
|
+
forEachChildren(tl, (/** @type {JSAnimation} */child) => {
|
|
1985
|
+
if (!tlIsRunningBackwards) {
|
|
1986
|
+
// Force an internal render to trigger the callbacks if the child has not completed on loop
|
|
1987
|
+
if (!child.completed && !child.backwards && child._currentTime < child.iterationDuration) {
|
|
1988
|
+
render(child, tlIterationDuration, muteCallbacks, 1, tickModes.FORCE);
|
|
1989
|
+
}
|
|
1990
|
+
// Reset their began and completed flags to allow retrigering callbacks on the next iteration
|
|
1991
|
+
child.began = false;
|
|
1992
|
+
child.completed = false;
|
|
1993
|
+
} else {
|
|
1994
|
+
const childDuration = child.duration;
|
|
1995
|
+
const childStartTime = child._offset + child._delay;
|
|
1996
|
+
const childEndTime = childStartTime + childDuration;
|
|
1997
|
+
// Triggers the onComplete callback on reverse for children on the edges of the timeline
|
|
1998
|
+
if (!muteCallbacks && childDuration <= minValue && (!childStartTime || childEndTime === tlIterationDuration)) {
|
|
1999
|
+
child.onComplete(child);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
});
|
|
1902
2003
|
if (!muteCallbacks) tl.onLoop(/** @type {CallbackArgument} */(tl));
|
|
1903
2004
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
tlChildrenHaveCompleted = renderCtxChildrenHaveCompleted;
|
|
2005
|
+
|
|
2006
|
+
forEachChildren(tl, (/** @type {JSAnimation} */child) => {
|
|
2007
|
+
const childTime = round$1((tlChildrenTime - child._offset) * child._speed, 12); // Rounding is needed when using seconds
|
|
2008
|
+
// 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.
|
|
2009
|
+
if (tlIsRunningBackwards && childTime > child._delay + child.duration) return;
|
|
2010
|
+
const childTickMode = child._fps < tl._fps ? child.requestTick(tlCildrenTickTime) : tickMode;
|
|
2011
|
+
tlChildrenHasRendered += render(child, childTime, muteCallbacks, internalRender, childTickMode);
|
|
2012
|
+
if (!child.completed && tlChildrenHaveCompleted) tlChildrenHaveCompleted = false;
|
|
2013
|
+
}, tlIsRunningBackwards);
|
|
2014
|
+
|
|
1915
2015
|
// Renders on timeline are triggered by its children so it needs to be set after rendering the children
|
|
1916
2016
|
if (!muteCallbacks && tlChildrenHasRendered) tl.onRender(/** @type {CallbackArgument} */(tl));
|
|
1917
2017
|
// Triggers the timeline onComplete() once all chindren all completed and the current time has reached the end
|
|
@@ -1983,7 +2083,20 @@ const revertValues = (renderable, inlineStylesOnly = false) => {
|
|
|
1983
2083
|
const tweenType = tween._tweenType;
|
|
1984
2084
|
const originalInlinedValue = tween._inlineValue;
|
|
1985
2085
|
const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
|
|
1986
|
-
if (
|
|
2086
|
+
if (tween._setter) {
|
|
2087
|
+
if (!inlineStylesOnly && !tweenHadNoInlineValue) {
|
|
2088
|
+
// 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.
|
|
2089
|
+
decomposeRawValue(originalInlinedValue, decomposedOriginalValue);
|
|
2090
|
+
if (decomposedOriginalValue.d) {
|
|
2091
|
+
const src = decomposedOriginalValue.d;
|
|
2092
|
+
const dst = tween._numbers;
|
|
2093
|
+
for (let i = 0, l = src.length; i < l; i++) dst[i] = src[i];
|
|
2094
|
+
} else {
|
|
2095
|
+
tween._number = decomposedOriginalValue.n;
|
|
2096
|
+
}
|
|
2097
|
+
tween._setter(tween.target, tween._number, tween);
|
|
2098
|
+
}
|
|
2099
|
+
} else if (tweenType === tweenTypes.OBJECT) {
|
|
1987
2100
|
if (!inlineStylesOnly && !tweenHadNoInlineValue) {
|
|
1988
2101
|
tweenTarget[tweenProperty] = originalInlinedValue;
|
|
1989
2102
|
}
|
|
@@ -2060,8 +2173,6 @@ class Clock {
|
|
|
2060
2173
|
/** @type {Number} */
|
|
2061
2174
|
this._lastTime = initTime;
|
|
2062
2175
|
/** @type {Number} */
|
|
2063
|
-
this._scheduledTime = 0;
|
|
2064
|
-
/** @type {Number} */
|
|
2065
2176
|
this._frameDuration = K / maxFps;
|
|
2066
2177
|
/** @type {Number} */
|
|
2067
2178
|
this._fps = maxFps;
|
|
@@ -2080,14 +2191,12 @@ class Clock {
|
|
|
2080
2191
|
}
|
|
2081
2192
|
|
|
2082
2193
|
set fps(frameRate) {
|
|
2083
|
-
const previousFrameDuration = this._frameDuration;
|
|
2084
2194
|
const fr = +frameRate;
|
|
2085
2195
|
const fps = fr < minValue ? minValue : fr;
|
|
2086
2196
|
const frameDuration = K / fps;
|
|
2087
2197
|
if (fps > defaults.frameRate) defaults.frameRate = fps;
|
|
2088
2198
|
this._fps = fps;
|
|
2089
2199
|
this._frameDuration = frameDuration;
|
|
2090
|
-
this._scheduledTime += frameDuration - previousFrameDuration;
|
|
2091
2200
|
}
|
|
2092
2201
|
|
|
2093
2202
|
get speed() {
|
|
@@ -2104,17 +2213,17 @@ class Clock {
|
|
|
2104
2213
|
* @return {tickModes}
|
|
2105
2214
|
*/
|
|
2106
2215
|
requestTick(time) {
|
|
2107
|
-
const scheduledTime = this._scheduledTime;
|
|
2108
|
-
this._lastTickTime = time;
|
|
2109
|
-
// If the current time is lower than the scheduled time
|
|
2110
|
-
// this means not enough time has passed to hit one frameDuration
|
|
2111
|
-
// so skip that frame
|
|
2112
|
-
if (time < scheduledTime) return tickModes.NONE;
|
|
2113
2216
|
const frameDuration = this._frameDuration;
|
|
2114
|
-
const
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2217
|
+
const elapsed = time - this._lastTickTime;
|
|
2218
|
+
const scaled = frameDuration * .25;
|
|
2219
|
+
const tolerance = scaled < 4 ? scaled : 4;
|
|
2220
|
+
// Tolerance prevents dropping frames that arrive a bit early due to RAF jitter
|
|
2221
|
+
// typically <= ~25% of frame duration and capped at 4ms so it doesn't dominate at high fps.
|
|
2222
|
+
// e.g. at 60fps (frameDuration=16.667ms) a frame arriving after 15ms:
|
|
2223
|
+
// - without tolerance: 15 < 16.667 -> skip
|
|
2224
|
+
// - with tolerance: 15 + 4 >= 16.667 -> tick
|
|
2225
|
+
if (elapsed + tolerance < frameDuration) return tickModes.NONE;
|
|
2226
|
+
this._lastTickTime = elapsed >= frameDuration ? time - (elapsed % frameDuration) : time;
|
|
2118
2227
|
return tickModes.AUTO;
|
|
2119
2228
|
}
|
|
2120
2229
|
|
|
@@ -2274,7 +2383,9 @@ class Engine extends Clock {
|
|
|
2274
2383
|
}
|
|
2275
2384
|
|
|
2276
2385
|
set speed(playbackRate) {
|
|
2277
|
-
|
|
2386
|
+
const speed = playbackRate * globals.timeScale;
|
|
2387
|
+
if (this._speed === speed) return;
|
|
2388
|
+
this._speed = speed;
|
|
2278
2389
|
forEachChildren(this, (/** @type {Tickable} */child) => child.speed = child._speed);
|
|
2279
2390
|
}
|
|
2280
2391
|
|
|
@@ -2407,7 +2518,7 @@ const composeTween = (tween, siblings) => {
|
|
|
2407
2518
|
if (prevSibling) {
|
|
2408
2519
|
|
|
2409
2520
|
const prevParent = prevSibling.parent;
|
|
2410
|
-
const prevAbsEndTime = prevSibling.
|
|
2521
|
+
const prevAbsEndTime = prevSibling._absoluteEndTime;
|
|
2411
2522
|
|
|
2412
2523
|
// Handle looped animations tween
|
|
2413
2524
|
|
|
@@ -2433,7 +2544,8 @@ const composeTween = (tween, siblings) => {
|
|
|
2433
2544
|
|
|
2434
2545
|
}
|
|
2435
2546
|
|
|
2436
|
-
|
|
2547
|
+
// 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.
|
|
2548
|
+
const absoluteUpdateStartTime = tween._absoluteUpdateStartTime;
|
|
2437
2549
|
|
|
2438
2550
|
if (prevAbsEndTime > absoluteUpdateStartTime) {
|
|
2439
2551
|
|
|
@@ -2453,37 +2565,41 @@ const composeTween = (tween, siblings) => {
|
|
|
2453
2565
|
}
|
|
2454
2566
|
}
|
|
2455
2567
|
|
|
2456
|
-
//
|
|
2568
|
+
// Skip the cancel cascade when both tweens share the same parent timeline, a timeline cannot replace itself.
|
|
2569
|
+
const tweenParentTL = tween.parent.parent;
|
|
2570
|
+
if (!tweenParentTL || tweenParentTL !== prevParent.parent) {
|
|
2457
2571
|
|
|
2458
|
-
|
|
2572
|
+
let pausePrevParentAnimation = true;
|
|
2459
2573
|
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2574
|
+
forEachChildren(prevParent, (/** @type Tween */t) => {
|
|
2575
|
+
if (!t._isOverlapped) pausePrevParentAnimation = false;
|
|
2576
|
+
});
|
|
2463
2577
|
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2578
|
+
if (pausePrevParentAnimation) {
|
|
2579
|
+
const prevParentTL = prevParent.parent;
|
|
2580
|
+
if (prevParentTL) {
|
|
2581
|
+
let pausePrevParentTL = true;
|
|
2582
|
+
forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
|
|
2583
|
+
if (a !== prevParent) {
|
|
2584
|
+
forEachChildren(a, (/** @type Tween */t) => {
|
|
2585
|
+
if (!t._isOverlapped) pausePrevParentTL = false;
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
});
|
|
2589
|
+
if (pausePrevParentTL) {
|
|
2590
|
+
prevParentTL.cancel();
|
|
2473
2591
|
}
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2592
|
+
} else {
|
|
2593
|
+
prevParent.cancel();
|
|
2594
|
+
// Previously, calling .cancel() on a timeline child would affect the render order of other children
|
|
2595
|
+
// Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
|
|
2596
|
+
// This is no longer needed since timeline tween composition is now handled separately
|
|
2597
|
+
// Keeping this here for reference
|
|
2598
|
+
// prevParent.completed = true;
|
|
2599
|
+
// prevParent.pause();
|
|
2477
2600
|
}
|
|
2478
|
-
} else {
|
|
2479
|
-
prevParent.cancel();
|
|
2480
|
-
// Previously, calling .cancel() on a timeline child would affect the render order of other children
|
|
2481
|
-
// Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
|
|
2482
|
-
// This is no longer needed since timeline tween composition is now handled separately
|
|
2483
|
-
// Keeping this here for reference
|
|
2484
|
-
// prevParent.completed = true;
|
|
2485
|
-
// prevParent.pause();
|
|
2486
2601
|
}
|
|
2602
|
+
|
|
2487
2603
|
}
|
|
2488
2604
|
|
|
2489
2605
|
}
|
|
@@ -2538,14 +2654,12 @@ const composeTween = (tween, siblings) => {
|
|
|
2538
2654
|
tween._number = 0;
|
|
2539
2655
|
lookupTween._fromNumber = toNumber;
|
|
2540
2656
|
|
|
2541
|
-
if (tween._toNumbers) {
|
|
2657
|
+
if (tween._toNumbers.length) {
|
|
2542
2658
|
const toNumbers = cloneArray(tween._toNumbers);
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
});
|
|
2548
|
-
}
|
|
2659
|
+
toNumbers.forEach((value, i) => {
|
|
2660
|
+
tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
|
|
2661
|
+
tween._toNumbers[i] = 0;
|
|
2662
|
+
});
|
|
2549
2663
|
lookupTween._fromNumbers = toNumbers;
|
|
2550
2664
|
}
|
|
2551
2665
|
|
|
@@ -3246,18 +3360,16 @@ function parseTargets(targets) {
|
|
|
3246
3360
|
function registerTargets(targets) {
|
|
3247
3361
|
const parsedTargetsArray = parseTargets(targets);
|
|
3248
3362
|
const parsedTargetsLength = parsedTargetsArray.length;
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
target[transformsSymbol] = {};
|
|
3260
|
-
}
|
|
3363
|
+
for (let i = 0; i < parsedTargetsLength; i++) {
|
|
3364
|
+
const target = parsedTargetsArray[i];
|
|
3365
|
+
if (!target[isRegisteredTargetSymbol]) {
|
|
3366
|
+
target[isRegisteredTargetSymbol] = true;
|
|
3367
|
+
const isSvgType = isSvg(target);
|
|
3368
|
+
const isDom = /** @type {DOMTarget} */(target).nodeType || isSvgType;
|
|
3369
|
+
if (isDom) {
|
|
3370
|
+
target[isDomSymbol] = true;
|
|
3371
|
+
target[isSvgSymbol] = isSvgType;
|
|
3372
|
+
target[transformsSymbol] = {};
|
|
3261
3373
|
}
|
|
3262
3374
|
}
|
|
3263
3375
|
}
|
|
@@ -3379,8 +3491,8 @@ const easeInFunctions = {
|
|
|
3379
3491
|
|
|
3380
3492
|
/**
|
|
3381
3493
|
* @typedef {Object} EasesFunctions
|
|
3382
|
-
* @property {
|
|
3383
|
-
* @property {
|
|
3494
|
+
* @property {EasingFunction} linear
|
|
3495
|
+
* @property {EasingFunction} none
|
|
3384
3496
|
* @property {PowerEasing} in
|
|
3385
3497
|
* @property {PowerEasing} out
|
|
3386
3498
|
* @property {PowerEasing} inOut
|
|
@@ -3612,6 +3724,11 @@ class JSAnimation extends Timer {
|
|
|
3612
3724
|
|
|
3613
3725
|
super(/** @type {TimerParams & AnimationParams} */(parameters), parent, parentPosition);
|
|
3614
3726
|
|
|
3727
|
+
/** @type {Tween} */
|
|
3728
|
+
this._head;
|
|
3729
|
+
/** @type {Tween} */
|
|
3730
|
+
this._tail;
|
|
3731
|
+
|
|
3615
3732
|
++JSAnimationId;
|
|
3616
3733
|
|
|
3617
3734
|
const parsedTargets = registerTargets(targets);
|
|
@@ -3668,6 +3785,7 @@ class JSAnimation extends Timer {
|
|
|
3668
3785
|
if (isKey(p)) {
|
|
3669
3786
|
|
|
3670
3787
|
const tweenType = getTweenType(target, p);
|
|
3788
|
+
const adapterProp = resolveAdapterEntry(target, p);
|
|
3671
3789
|
|
|
3672
3790
|
const propName = sanitizePropertyName(p, target, tweenType);
|
|
3673
3791
|
|
|
@@ -3751,7 +3869,7 @@ class JSAnimation extends Timer {
|
|
|
3751
3869
|
} else {
|
|
3752
3870
|
tweenToValue = computedToValue;
|
|
3753
3871
|
}
|
|
3754
|
-
const tweenFromValue = getFunctionValue(key.from, target, ti, tl,
|
|
3872
|
+
const tweenFromValue = getFunctionValue(key.from, target, ti, tl, fromFunctionStore, prevSiblingTween);
|
|
3755
3873
|
const easeToParse = key.ease || tEasing;
|
|
3756
3874
|
|
|
3757
3875
|
const easeFunctionResult = getFunctionValue(easeToParse, target, ti, tl, null, prevSiblingTween);
|
|
@@ -3769,9 +3887,13 @@ class JSAnimation extends Timer {
|
|
|
3769
3887
|
const hasToValue = !isUnd(tweenToValue);
|
|
3770
3888
|
const isFromToArray = isArr(tweenToValue);
|
|
3771
3889
|
const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
|
|
3890
|
+
// 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.
|
|
3891
|
+
const tweenUpdateStartLocal = prevTween ? lastTweenChangeEndTime : 0;
|
|
3772
3892
|
const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
|
|
3773
3893
|
// Rounding is necessary here to minimize floating point errors when working in seconds
|
|
3774
3894
|
const absoluteStartTime = round$1(absoluteOffsetTime + tweenStartTime, 12);
|
|
3895
|
+
// Match the rounding pattern of prevSibling._absoluteEndTime so the composition overlap check compares cleanly when keyframes touch at a boundary.
|
|
3896
|
+
const absoluteUpdateStartTime = round$1(absoluteOffsetTime + tweenUpdateStartLocal, 12);
|
|
3775
3897
|
|
|
3776
3898
|
// Force a onRender callback if the animation contains at least one from value and autoplay is set to false
|
|
3777
3899
|
if (!shouldTriggerRender && (hasFromvalue || isFromToArray)) shouldTriggerRender = 1;
|
|
@@ -3780,9 +3902,9 @@ class JSAnimation extends Timer {
|
|
|
3780
3902
|
|
|
3781
3903
|
if (tweenComposition !== compositionTypes.none) {
|
|
3782
3904
|
let nextSibling = siblings._head;
|
|
3783
|
-
//
|
|
3784
|
-
while (nextSibling &&
|
|
3785
|
-
prevSibling = nextSibling;
|
|
3905
|
+
// 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.
|
|
3906
|
+
while (nextSibling && nextSibling._absoluteStartTime <= absoluteStartTime) {
|
|
3907
|
+
if (!nextSibling._isOverridden) prevSibling = nextSibling;
|
|
3786
3908
|
nextSibling = nextSibling._nextRep;
|
|
3787
3909
|
// Overrides all the next siblings if the next sibling starts at the same time of after as the new tween start time
|
|
3788
3910
|
if (nextSibling && nextSibling._absoluteStartTime >= absoluteStartTime) {
|
|
@@ -3836,8 +3958,8 @@ class JSAnimation extends Timer {
|
|
|
3836
3958
|
if (prevTween) {
|
|
3837
3959
|
decomposeTweenValue(prevTween, fromTargetObject);
|
|
3838
3960
|
} else {
|
|
3839
|
-
decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
|
|
3840
3961
|
// 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
|
|
3962
|
+
decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
|
|
3841
3963
|
getOriginalAnimatableValue(target, propName, tweenType, inlineStylesStore), fromTargetObject);
|
|
3842
3964
|
}
|
|
3843
3965
|
}
|
|
@@ -3876,8 +3998,7 @@ class JSAnimation extends Timer {
|
|
|
3876
3998
|
const colorValue = fromTargetObject.t === valueTypes.COLOR ? fromTargetObject : toTargetObject;
|
|
3877
3999
|
const notColorValue = fromTargetObject.t === valueTypes.COLOR ? toTargetObject : fromTargetObject;
|
|
3878
4000
|
notColorValue.t = valueTypes.COLOR;
|
|
3879
|
-
notColorValue.
|
|
3880
|
-
notColorValue.d = [0, 0, 0, 1];
|
|
4001
|
+
notColorValue.d = colorValue.d.map(() => 0);
|
|
3881
4002
|
}
|
|
3882
4003
|
}
|
|
3883
4004
|
|
|
@@ -3907,6 +4028,16 @@ class JSAnimation extends Timer {
|
|
|
3907
4028
|
let inlineValue = inlineStylesStore[propName];
|
|
3908
4029
|
if (!isNil(inlineValue)) inlineStylesStore[propName] = null;
|
|
3909
4030
|
|
|
4031
|
+
// Resolve the adapter setter once so render skips the lookup per frame.
|
|
4032
|
+
const tweenSetter = adapterProp ? adapterProp.set : null;
|
|
4033
|
+
|
|
4034
|
+
// Rounding is necessary here to minimize floating point errors when working in seconds
|
|
4035
|
+
lastTweenChangeEndTime = round$1(tweenStartTime + tweenUpdateDuration, 12);
|
|
4036
|
+
|
|
4037
|
+
const fromD = fromTargetObject.d;
|
|
4038
|
+
const toD = toTargetObject.d;
|
|
4039
|
+
const toS = toTargetObject.s;
|
|
4040
|
+
|
|
3910
4041
|
/** @type {Tween} */
|
|
3911
4042
|
const tween = {
|
|
3912
4043
|
parent: this,
|
|
@@ -3917,12 +4048,12 @@ class JSAnimation extends Timer {
|
|
|
3917
4048
|
_toFunc: toFunctionStore.func,
|
|
3918
4049
|
_fromFunc: fromFunctionStore.func,
|
|
3919
4050
|
_ease: parseEase(tweenEasing),
|
|
3920
|
-
_fromNumbers: cloneArray(
|
|
3921
|
-
_toNumbers: cloneArray(
|
|
3922
|
-
_strings: cloneArray(
|
|
4051
|
+
_fromNumbers: fromD ? cloneArray(fromD) : emptyArray,
|
|
4052
|
+
_toNumbers: toD ? cloneArray(toD) : emptyArray,
|
|
4053
|
+
_strings: toS ? cloneArray(toS) : emptyArray,
|
|
3923
4054
|
_fromNumber: fromTargetObject.n,
|
|
3924
4055
|
_toNumber: toTargetObject.n,
|
|
3925
|
-
_numbers: cloneArray(
|
|
4056
|
+
_numbers: fromD ? cloneArray(fromD) : emptyArray, // For additive tween and animatables
|
|
3926
4057
|
_number: fromTargetObject.n, // For additive tween and animatables
|
|
3927
4058
|
_unit: toTargetObject.u,
|
|
3928
4059
|
_modifier: tweenModifier,
|
|
@@ -3932,8 +4063,12 @@ class JSAnimation extends Timer {
|
|
|
3932
4063
|
_updateDuration: tweenUpdateDuration,
|
|
3933
4064
|
_changeDuration: tweenUpdateDuration,
|
|
3934
4065
|
_absoluteStartTime: absoluteStartTime,
|
|
4066
|
+
_absoluteUpdateStartTime: absoluteUpdateStartTime,
|
|
4067
|
+
_absoluteEndTime: round$1(absoluteOffsetTime + lastTweenChangeEndTime, 12),
|
|
4068
|
+
_hasFromValue: hasFromvalue || isFromToArray ? 1 : 0,
|
|
3935
4069
|
// NOTE: Investigate bit packing to stores ENUM / BOOL
|
|
3936
4070
|
_tweenType: tweenType,
|
|
4071
|
+
_setter: tweenSetter,
|
|
3937
4072
|
_valueType: toTargetObject.t,
|
|
3938
4073
|
_composition: tweenComposition,
|
|
3939
4074
|
_isOverlapped: 0,
|
|
@@ -3956,10 +4091,11 @@ class JSAnimation extends Timer {
|
|
|
3956
4091
|
const vt = tween._valueType;
|
|
3957
4092
|
if (vt === valueTypes.COMPLEX) {
|
|
3958
4093
|
tween._value = composeComplexValue(tween, 1, -1);
|
|
3959
|
-
} else if (vt === valueTypes.COLOR) {
|
|
3960
|
-
tween._value = composeColorValue(tween, 1, -1);
|
|
3961
4094
|
} else if (vt === valueTypes.UNIT) {
|
|
3962
4095
|
tween._value = `${tweenModifier(tween._toNumber)}${tween._unit}`;
|
|
4096
|
+
} else if (vt === valueTypes.COLOR) {
|
|
4097
|
+
const d = toTargetObject.d;
|
|
4098
|
+
tween._value = `rgba(${round$1(d[0], 0)},${round$1(d[1], 0)},${round$1(d[2], 0)},${d[3]})`;
|
|
3963
4099
|
} else {
|
|
3964
4100
|
tween._value = tweenModifier(tween._toNumber);
|
|
3965
4101
|
}
|
|
@@ -3967,8 +4103,7 @@ class JSAnimation extends Timer {
|
|
|
3967
4103
|
if (isNaN(firstTweenChangeStartTime)) {
|
|
3968
4104
|
firstTweenChangeStartTime = tween._startTime;
|
|
3969
4105
|
}
|
|
3970
|
-
|
|
3971
|
-
lastTweenChangeEndTime = round$1(tweenStartTime + tweenUpdateDuration, 12);
|
|
4106
|
+
|
|
3972
4107
|
prevTween = tween;
|
|
3973
4108
|
animationAnimationLength++;
|
|
3974
4109
|
|
|
@@ -4074,8 +4209,11 @@ class JSAnimation extends Timer {
|
|
|
4074
4209
|
tween._updateDuration = normalizeTime(tween._updateDuration * timeScale);
|
|
4075
4210
|
tween._changeDuration = normalizeTime(tween._changeDuration * timeScale);
|
|
4076
4211
|
tween._currentTime *= timeScale;
|
|
4212
|
+
tween._delay *= timeScale;
|
|
4077
4213
|
tween._startTime *= timeScale;
|
|
4078
4214
|
tween._absoluteStartTime *= timeScale;
|
|
4215
|
+
tween._absoluteUpdateStartTime *= timeScale;
|
|
4216
|
+
tween._absoluteEndTime *= timeScale;
|
|
4079
4217
|
});
|
|
4080
4218
|
return super.stretch(newDuration);
|
|
4081
4219
|
}
|
|
@@ -4204,8 +4342,6 @@ const parseTimelinePosition = (timeline, timePosition) => {
|
|
|
4204
4342
|
|
|
4205
4343
|
|
|
4206
4344
|
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
4345
|
/**
|
|
4210
4346
|
* @param {Timeline} tl
|
|
4211
4347
|
* @return {Number}
|
|
@@ -4398,13 +4534,21 @@ class Timeline extends Timer {
|
|
|
4398
4534
|
if (!isUnd(synced) && !isUnd(/** @type {WAAPIAnimation} */(synced).persist)) {
|
|
4399
4535
|
/** @type {WAAPIAnimation} */(synced).persist = true;
|
|
4400
4536
|
}
|
|
4401
|
-
|
|
4537
|
+
const editor = globals.editor;
|
|
4538
|
+
const childHook = editor && editor.addTimelineChild;
|
|
4539
|
+
if (editor && editor.addTimelineSync) {
|
|
4540
|
+
position = editor.addTimelineSync(synced, position, this.id);
|
|
4541
|
+
editor.addTimelineChild = null; // Suppress the per-child hook for the internal .add, sync already registered.
|
|
4542
|
+
}
|
|
4543
|
+
const result = this.add(synced, { currentTime: [0, duration], duration, delay: 0, ease: 'linear', playbackEase: 'linear' }, position);
|
|
4544
|
+
if (editor) editor.addTimelineChild = childHook;
|
|
4545
|
+
return result;
|
|
4402
4546
|
}
|
|
4403
4547
|
|
|
4404
4548
|
/**
|
|
4405
4549
|
* @param {TargetsParam} targets
|
|
4406
4550
|
* @param {AnimationParams} parameters
|
|
4407
|
-
* @param {TimelinePosition} [position]
|
|
4551
|
+
* @param {TimelinePosition|StaggerFunction<Number|String>|TweakRegister} [position]
|
|
4408
4552
|
* @return {this}
|
|
4409
4553
|
*/
|
|
4410
4554
|
set(targets, parameters, position) {
|
|
@@ -4421,6 +4565,7 @@ class Timeline extends Timer {
|
|
|
4421
4565
|
*/
|
|
4422
4566
|
call(callback, position) {
|
|
4423
4567
|
if (isUnd(callback) || callback && !isFnc(callback)) return this;
|
|
4568
|
+
if (globals.editor && globals.editor.addTimelineCall) position = globals.editor.addTimelineCall(callback, position, this.id);
|
|
4424
4569
|
return this.add({ duration: 0, delay: 0, onComplete: () => callback(this) }, position);
|
|
4425
4570
|
}
|
|
4426
4571
|
|
|
@@ -4432,6 +4577,7 @@ class Timeline extends Timer {
|
|
|
4432
4577
|
*/
|
|
4433
4578
|
label(labelName, position) {
|
|
4434
4579
|
if (isUnd(labelName) || labelName && !isStr(labelName)) return this;
|
|
4580
|
+
if (globals.editor && globals.editor.addTimelineLabel) position = globals.editor.addTimelineLabel(labelName, position, this.id);
|
|
4435
4581
|
this.labels[labelName] = parseTimelinePosition(this, position);
|
|
4436
4582
|
return this;
|
|
4437
4583
|
}
|
|
@@ -4540,6 +4686,7 @@ class Animatable {
|
|
|
4540
4686
|
const callbacksAnimationParams = { v: 1, autoplay: false };
|
|
4541
4687
|
const properties = {};
|
|
4542
4688
|
this.targets = [];
|
|
4689
|
+
/** @type {Record<String, JSAnimation>} */
|
|
4543
4690
|
this.animations = {};
|
|
4544
4691
|
/** @type {JSAnimation|null} */
|
|
4545
4692
|
this.callbacks = null;
|
|
@@ -5078,6 +5225,9 @@ function get(targetSelector, propName, unit) {
|
|
|
5078
5225
|
*/
|
|
5079
5226
|
const set = (targets, parameters) => {
|
|
5080
5227
|
if (isUnd(parameters)) return;
|
|
5228
|
+
if (globals.editor && globals.editor.addSet) {
|
|
5229
|
+
return globals.editor.addSet(targets, parameters);
|
|
5230
|
+
}
|
|
5081
5231
|
parameters.duration = minValue;
|
|
5082
5232
|
// Do not overrides currently active tweens by default
|
|
5083
5233
|
parameters.composition = setValue(parameters.composition, compositionTypes.none);
|
|
@@ -6314,13 +6464,14 @@ const sync = (callback = noop) => {
|
|
|
6314
6464
|
};
|
|
6315
6465
|
|
|
6316
6466
|
/**
|
|
6317
|
-
* @
|
|
6318
|
-
* @
|
|
6467
|
+
* @template {Tickable | ((...args: any[]) => void) | void} T
|
|
6468
|
+
* @param {(...args: any[]) => T} constructor
|
|
6469
|
+
* @return {(...args: any[]) => T extends void ? () => void : T}
|
|
6319
6470
|
*/
|
|
6320
6471
|
const keepTime = constructor => {
|
|
6321
6472
|
/** @type {Tickable} */
|
|
6322
6473
|
let tracked;
|
|
6323
|
-
return (...args) => {
|
|
6474
|
+
return /** @type {(...args: any[]) => T extends void ? () => void : T} */(/** @type {*} */((...args) => {
|
|
6324
6475
|
let currentIteration, currentIterationProgress, reversed, alternate, startTime;
|
|
6325
6476
|
if (tracked) {
|
|
6326
6477
|
currentIteration = tracked.currentIteration;
|
|
@@ -6338,7 +6489,7 @@ const keepTime = constructor => {
|
|
|
6338
6489
|
/** @type {Tickable} */(tracked)._startTime = startTime;
|
|
6339
6490
|
}
|
|
6340
6491
|
return cleanup || noop;
|
|
6341
|
-
}
|
|
6492
|
+
}));
|
|
6342
6493
|
};
|
|
6343
6494
|
|
|
6344
6495
|
|
|
@@ -6736,12 +6887,14 @@ class ScrollContainer {
|
|
|
6736
6887
|
|
|
6737
6888
|
refreshScrollObservers() {
|
|
6738
6889
|
forEachChildren(this, (/** @type {ScrollObserver} */child) => {
|
|
6890
|
+
if (!child.ready) return;
|
|
6739
6891
|
if (child._debug) {
|
|
6740
6892
|
child.removeDebug();
|
|
6741
6893
|
}
|
|
6742
6894
|
});
|
|
6743
6895
|
this.updateBounds();
|
|
6744
6896
|
forEachChildren(this, (/** @type {ScrollObserver} */child) => {
|
|
6897
|
+
if (!child.ready) return;
|
|
6745
6898
|
child.refresh();
|
|
6746
6899
|
child.onResize(child);
|
|
6747
6900
|
if (child._debug) {
|
|
@@ -9839,11 +9992,12 @@ const randomPick = items => items[random(0, items.length - 1)];
|
|
|
9839
9992
|
* Adapted from https://bost.ocks.org/mike/shuffle/
|
|
9840
9993
|
*
|
|
9841
9994
|
* @param {Array} items - The array to shuffle (will be modified in-place)
|
|
9995
|
+
* @param {RandomNumberGenerator} [rnd] - Optional RNG matching the random() signature (defaults to random)
|
|
9842
9996
|
* @return {Array} The same array reference, now shuffled
|
|
9843
9997
|
*/
|
|
9844
|
-
const shuffle = items => {
|
|
9998
|
+
const shuffle = (items, rnd = random) => {
|
|
9845
9999
|
let m = items.length, t, i;
|
|
9846
|
-
while (m) { i =
|
|
10000
|
+
while (m) { i = rnd(0, --m); t = items[m]; items[m] = items[i]; items[i] = t; }
|
|
9847
10001
|
return items;
|
|
9848
10002
|
};
|
|
9849
10003
|
|
|
@@ -9888,6 +10042,7 @@ const stagger = (val, params = {}) => {
|
|
|
9888
10042
|
let values = [];
|
|
9889
10043
|
let maxValue = 0;
|
|
9890
10044
|
let cachedOffset;
|
|
10045
|
+
let jitterSamples = null;
|
|
9891
10046
|
const from = params.from;
|
|
9892
10047
|
const reversed = params.reversed;
|
|
9893
10048
|
const ease = params.ease;
|
|
@@ -9909,27 +10064,42 @@ const stagger = (val, params = {}) => {
|
|
|
9909
10064
|
const val2 = isRange ? parseNumber(val[1]) : 0;
|
|
9910
10065
|
const unitMatch = unitsExecRgx.exec((isRange ? val[1] : val) + emptyString);
|
|
9911
10066
|
const start = params.start || 0 + (isRange ? val1 : 0);
|
|
10067
|
+
const seed = params.seed;
|
|
10068
|
+
const hasSeed = !isUnd(seed) && seed !== false;
|
|
10069
|
+
const rng = hasSeed ? createSeededRandom(seed === true ? 0 : /** @type {Number} */(seed)) : random;
|
|
10070
|
+
const jitter = params.jitter;
|
|
10071
|
+
const hasJitter = !isUnd(jitter);
|
|
10072
|
+
const jitterIsArr = isArr(jitter);
|
|
10073
|
+
const jitterStart = jitterIsArr ? /** @type {[Number,Number]} */(jitter)[0] : /** @type {Number} */(jitter) || 0;
|
|
10074
|
+
const jitterEnd = jitterIsArr ? /** @type {[Number,Number]} */(jitter)[1] : /** @type {Number} */(jitter) || 0;
|
|
9912
10075
|
let fromIndex = fromFirst ? 0 : isNum(from) ? from : 0;
|
|
9913
10076
|
return (target, i, t, _, tl) => {
|
|
9914
10077
|
const [ registeredTarget ] = registerTargets(target);
|
|
9915
10078
|
const total = isUnd(customTotal) ? t.length : customTotal;
|
|
9916
10079
|
const customIndex = !isUnd(useProp) ? isFnc(useProp) ? useProp(registeredTarget, i, total) : getOriginalAnimatableValue(registeredTarget, useProp) : false;
|
|
9917
|
-
const
|
|
10080
|
+
const customIdx = isNum(customIndex) || isStr(customIndex) && isNum(+customIndex) ? +customIndex : i;
|
|
10081
|
+
// Fall back to the natural index when the resolved value lands outside [0, total) so values[staggerIndex] never reads undefined.
|
|
10082
|
+
const staggerIndex = customIdx >= 0 && customIdx < total ? customIdx : i;
|
|
9918
10083
|
if (fromCenter) fromIndex = (total - 1) / 2;
|
|
9919
10084
|
if (fromLast) fromIndex = total - 1;
|
|
9920
10085
|
if (!values.length) {
|
|
9921
10086
|
if (autoGrid) {
|
|
9922
10087
|
let hasPositions = true;
|
|
10088
|
+
let has3D = false;
|
|
9923
10089
|
let minPosX = Infinity;
|
|
9924
10090
|
let minPosY = Infinity;
|
|
10091
|
+
let minPosZ = Infinity;
|
|
9925
10092
|
let maxPosX = -Infinity;
|
|
9926
10093
|
let maxPosY = -Infinity;
|
|
10094
|
+
let maxPosZ = -Infinity;
|
|
9927
10095
|
const pxArr = [];
|
|
9928
10096
|
const pyArr = [];
|
|
10097
|
+
const pzArr = [];
|
|
9929
10098
|
for (let index = 0; index < total; index++) {
|
|
9930
10099
|
const el = t[index];
|
|
9931
10100
|
let px = 0;
|
|
9932
10101
|
let py = 0;
|
|
10102
|
+
let pz = 0;
|
|
9933
10103
|
let found = false;
|
|
9934
10104
|
if (el && isFnc(el.getBoundingClientRect)) {
|
|
9935
10105
|
const rect = el.getBoundingClientRect();
|
|
@@ -9941,6 +10111,10 @@ const stagger = (val, params = {}) => {
|
|
|
9941
10111
|
if (obj && isNum(obj.x) && isNum(obj.y)) {
|
|
9942
10112
|
px = obj.x;
|
|
9943
10113
|
py = obj.y;
|
|
10114
|
+
if (isNum(obj.z)) {
|
|
10115
|
+
pz = obj.z;
|
|
10116
|
+
has3D = true;
|
|
10117
|
+
}
|
|
9944
10118
|
found = true;
|
|
9945
10119
|
}
|
|
9946
10120
|
}
|
|
@@ -9950,42 +10124,52 @@ const stagger = (val, params = {}) => {
|
|
|
9950
10124
|
}
|
|
9951
10125
|
pxArr.push(px);
|
|
9952
10126
|
pyArr.push(py);
|
|
10127
|
+
pzArr.push(pz);
|
|
9953
10128
|
if (px < minPosX) minPosX = px;
|
|
9954
10129
|
if (py < minPosY) minPosY = py;
|
|
10130
|
+
if (pz < minPosZ) minPosZ = pz;
|
|
9955
10131
|
if (px > maxPosX) maxPosX = px;
|
|
9956
10132
|
if (py > maxPosY) maxPosY = py;
|
|
10133
|
+
if (pz > maxPosZ) maxPosZ = pz;
|
|
9957
10134
|
}
|
|
9958
10135
|
if (hasPositions) {
|
|
9959
10136
|
let fX = pxArr[0];
|
|
9960
10137
|
let fY = pyArr[0];
|
|
10138
|
+
let fZ = pzArr[0];
|
|
9961
10139
|
if (fromArr) {
|
|
9962
10140
|
fX = minPosX + from[0] * (maxPosX - minPosX);
|
|
9963
10141
|
fY = minPosY + from[1] * (maxPosY - minPosY);
|
|
10142
|
+
fZ = has3D ? minPosZ + (from.length >= 3 ? from[2] : 0.5) * (maxPosZ - minPosZ) : 0;
|
|
9964
10143
|
} else if (fromCenter) {
|
|
9965
10144
|
fX = (minPosX + maxPosX) / 2;
|
|
9966
10145
|
fY = (minPosY + maxPosY) / 2;
|
|
10146
|
+
fZ = (minPosZ + maxPosZ) / 2;
|
|
9967
10147
|
} else if (fromLast) {
|
|
9968
10148
|
fX = pxArr[total - 1];
|
|
9969
10149
|
fY = pyArr[total - 1];
|
|
10150
|
+
fZ = pzArr[total - 1];
|
|
9970
10151
|
} else if (isNum(from)) {
|
|
9971
10152
|
fX = pxArr[from];
|
|
9972
10153
|
fY = pyArr[from];
|
|
10154
|
+
fZ = pzArr[from];
|
|
9973
10155
|
}
|
|
9974
10156
|
for (let index = 0; index < total; index++) {
|
|
9975
10157
|
const distanceX = fX - pxArr[index];
|
|
9976
10158
|
const distanceY = fY - pyArr[index];
|
|
9977
|
-
|
|
10159
|
+
const distanceZ = fZ - pzArr[index];
|
|
10160
|
+
let value = sqrt(distanceX * distanceX + distanceY * distanceY + (has3D ? distanceZ * distanceZ : 0));
|
|
9978
10161
|
if (axis === 'x') value = -distanceX;
|
|
9979
10162
|
if (axis === 'y') value = -distanceY;
|
|
10163
|
+
if (axis === 'z') value = -distanceZ;
|
|
9980
10164
|
values.push(value);
|
|
9981
10165
|
}
|
|
9982
10166
|
let minDist = Infinity;
|
|
9983
|
-
for (let index = 0
|
|
10167
|
+
for (let index = 0; index < total; index++) {
|
|
9984
10168
|
const absVal = abs(values[index]);
|
|
9985
10169
|
if (absVal > 0 && absVal < minDist) minDist = absVal;
|
|
9986
10170
|
}
|
|
9987
10171
|
if (minDist > 0 && minDist < Infinity) {
|
|
9988
|
-
for (let index = 0
|
|
10172
|
+
for (let index = 0; index < total; index++) {
|
|
9989
10173
|
values[index] = values[index] / minDist;
|
|
9990
10174
|
}
|
|
9991
10175
|
}
|
|
@@ -9999,32 +10183,51 @@ const stagger = (val, params = {}) => {
|
|
|
9999
10183
|
if (!grid) {
|
|
10000
10184
|
values.push(abs(fromIndex - index));
|
|
10001
10185
|
} else {
|
|
10002
|
-
|
|
10186
|
+
const dims = grid.length;
|
|
10187
|
+
const wh = grid[0] * grid[1];
|
|
10188
|
+
let fromX, fromY, fromZ;
|
|
10003
10189
|
if (fromArr) {
|
|
10004
10190
|
fromX = from[0] * (grid[0] - 1);
|
|
10005
10191
|
fromY = from[1] * (grid[1] - 1);
|
|
10192
|
+
fromZ = dims === 3 ? (from.length >= 3 ? from[2] : 0.5) * (grid[2] - 1) : 0;
|
|
10006
10193
|
} else if (fromCenter) {
|
|
10007
10194
|
fromX = (grid[0] - 1) / 2;
|
|
10008
10195
|
fromY = (grid[1] - 1) / 2;
|
|
10196
|
+
fromZ = dims === 3 ? (grid[2] - 1) / 2 : 0;
|
|
10009
10197
|
} else {
|
|
10010
10198
|
fromX = fromIndex % grid[0];
|
|
10011
|
-
fromY = floor(fromIndex / grid[0]);
|
|
10199
|
+
fromY = floor(fromIndex / grid[0]) % grid[1];
|
|
10200
|
+
fromZ = dims === 3 ? floor(fromIndex / wh) : 0;
|
|
10012
10201
|
}
|
|
10013
10202
|
const toX = index % grid[0];
|
|
10014
|
-
const toY = floor(index / grid[0]);
|
|
10203
|
+
const toY = floor(index / grid[0]) % grid[1];
|
|
10204
|
+
const toZ = dims === 3 ? floor(index / wh) : 0;
|
|
10015
10205
|
const distanceX = fromX - toX;
|
|
10016
10206
|
const distanceY = fromY - toY;
|
|
10017
|
-
|
|
10207
|
+
const distanceZ = fromZ - toZ;
|
|
10208
|
+
let value = sqrt(distanceX * distanceX + distanceY * distanceY + (dims === 3 ? distanceZ * distanceZ : 0));
|
|
10018
10209
|
if (axis === 'x') value = -distanceX;
|
|
10019
10210
|
if (axis === 'y') value = -distanceY;
|
|
10211
|
+
if (axis === 'z') value = -distanceZ;
|
|
10020
10212
|
values.push(value);
|
|
10021
10213
|
}
|
|
10022
10214
|
}
|
|
10023
10215
|
}
|
|
10024
|
-
maxValue =
|
|
10025
|
-
|
|
10026
|
-
if (
|
|
10027
|
-
|
|
10216
|
+
maxValue = values[0];
|
|
10217
|
+
for (let k = 1; k < total; k++) if (values[k] > maxValue) maxValue = values[k];
|
|
10218
|
+
if (staggerEase || reversed) {
|
|
10219
|
+
for (let k = 0; k < total; k++) {
|
|
10220
|
+
let v = values[k];
|
|
10221
|
+
if (staggerEase) v = staggerEase(v / maxValue) * maxValue;
|
|
10222
|
+
if (reversed) v = axis ? -v : abs(maxValue - v);
|
|
10223
|
+
values[k] = v;
|
|
10224
|
+
}
|
|
10225
|
+
}
|
|
10226
|
+
if (hasJitter) {
|
|
10227
|
+
jitterSamples = new Array(total);
|
|
10228
|
+
for (let k = 0; k < total; k++) jitterSamples[k] = rng(-1, 1, 4);
|
|
10229
|
+
}
|
|
10230
|
+
if (fromRandom) values = shuffle(values, rng);
|
|
10028
10231
|
}
|
|
10029
10232
|
const spacing = isRange ? (val2 - val1) / maxValue : val1;
|
|
10030
10233
|
if (isUnd(cachedOffset)) {
|
|
@@ -10032,6 +10235,11 @@ const stagger = (val, params = {}) => {
|
|
|
10032
10235
|
}
|
|
10033
10236
|
/** @type {String|Number} */
|
|
10034
10237
|
let output = cachedOffset + ((spacing * round$1(values[staggerIndex], 2)) || 0);
|
|
10238
|
+
if (hasJitter) {
|
|
10239
|
+
const progress = maxValue ? values[staggerIndex] / maxValue : 0;
|
|
10240
|
+
const mag = jitterStart + (jitterEnd - jitterStart) * progress;
|
|
10241
|
+
output = /** @type {Number} */(output) + jitterSamples[staggerIndex] * mag;
|
|
10242
|
+
}
|
|
10035
10243
|
if (params.modifier) output = params.modifier(/** @type {Number} */(output));
|
|
10036
10244
|
if (unitMatch) output = `${output}${unitMatch[2]}`;
|
|
10037
10245
|
return output;
|
|
@@ -10401,6 +10609,7 @@ const filterLineElements = ($el, lineIndex, bin) => {
|
|
|
10401
10609
|
*/
|
|
10402
10610
|
const generateTemplate = (type, params = {}) => {
|
|
10403
10611
|
let template = ``;
|
|
10612
|
+
if (!params) params = {};
|
|
10404
10613
|
const classString = isStr(params.class) ? ` class="${params.class}"` : '';
|
|
10405
10614
|
const cloneType = setValue(params.clone, false);
|
|
10406
10615
|
const wrapType = setValue(params.wrap, false);
|
|
@@ -10782,6 +10991,16 @@ const split = (target, parameters) => {
|
|
|
10782
10991
|
|
|
10783
10992
|
|
|
10784
10993
|
|
|
10994
|
+
/**
|
|
10995
|
+
* @typedef {Object} ScrambleTextTween
|
|
10996
|
+
* @property {Number} from
|
|
10997
|
+
* @property {Number} to
|
|
10998
|
+
* @property {Number} duration
|
|
10999
|
+
* @property {Number} delay
|
|
11000
|
+
* @property {String} ease
|
|
11001
|
+
* @property {(v: Number) => String} modifier
|
|
11002
|
+
*/
|
|
11003
|
+
|
|
10785
11004
|
/**
|
|
10786
11005
|
* '-' 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-')
|
|
10787
11006
|
* @param {String} str
|
|
@@ -10819,7 +11038,7 @@ const originalTexts = new WeakMap();
|
|
|
10819
11038
|
* progressively revealing the original text.
|
|
10820
11039
|
*
|
|
10821
11040
|
* @param {ScrambleTextParams} [params]
|
|
10822
|
-
* @return {FunctionValue}
|
|
11041
|
+
* @return {FunctionValue<ScrambleTextTween>}
|
|
10823
11042
|
*/
|
|
10824
11043
|
const scrambleText = (params = {}) => {
|
|
10825
11044
|
if (!params) params = {};
|