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.
Files changed (165) hide show
  1. package/README.md +4 -5
  2. package/dist/bundles/anime.esm.js +491 -272
  3. package/dist/bundles/anime.esm.min.js +2 -2
  4. package/dist/bundles/anime.umd.js +491 -272
  5. package/dist/bundles/anime.umd.min.js +2 -2
  6. package/dist/modules/adapters/index.cjs +14 -0
  7. package/dist/modules/adapters/index.d.ts +1 -0
  8. package/dist/modules/adapters/index.js +8 -0
  9. package/dist/modules/adapters/registry.cjs +149 -0
  10. package/dist/modules/adapters/registry.d.ts +65 -0
  11. package/dist/modules/adapters/registry.js +146 -0
  12. package/dist/modules/adapters/three/adapter.cjs +26 -0
  13. package/dist/modules/adapters/three/adapter.d.ts +15 -0
  14. package/dist/modules/adapters/three/adapter.js +24 -0
  15. package/dist/modules/adapters/three/helpers.cjs +297 -0
  16. package/dist/modules/adapters/three/helpers.d.ts +89 -0
  17. package/dist/modules/adapters/three/helpers.js +280 -0
  18. package/dist/modules/adapters/three/index.cjs +20 -0
  19. package/dist/modules/adapters/three/index.d.ts +2 -0
  20. package/dist/modules/adapters/three/index.js +12 -0
  21. package/dist/modules/adapters/three/instance.cjs +368 -0
  22. package/dist/modules/adapters/three/instance.d.ts +133 -0
  23. package/dist/modules/adapters/three/instance.js +365 -0
  24. package/dist/modules/adapters/three/object3d.cjs +214 -0
  25. package/dist/modules/adapters/three/object3d.d.ts +1 -0
  26. package/dist/modules/adapters/three/object3d.js +212 -0
  27. package/dist/modules/adapters/three/resolvers.cjs +105 -0
  28. package/dist/modules/adapters/three/resolvers.d.ts +1 -0
  29. package/dist/modules/adapters/three/resolvers.js +103 -0
  30. package/dist/modules/adapters/three/uniform.cjs +41 -0
  31. package/dist/modules/adapters/three/uniform.d.ts +1 -0
  32. package/dist/modules/adapters/three/uniform.js +39 -0
  33. package/dist/modules/animatable/animatable.cjs +2 -1
  34. package/dist/modules/animatable/animatable.d.ts +2 -1
  35. package/dist/modules/animatable/animatable.js +2 -1
  36. package/dist/modules/animatable/index.cjs +1 -1
  37. package/dist/modules/animatable/index.js +1 -1
  38. package/dist/modules/animation/additive.cjs +1 -1
  39. package/dist/modules/animation/additive.js +1 -1
  40. package/dist/modules/animation/animation.cjs +43 -16
  41. package/dist/modules/animation/animation.d.ts +5 -0
  42. package/dist/modules/animation/animation.js +45 -18
  43. package/dist/modules/animation/composition.cjs +38 -35
  44. package/dist/modules/animation/composition.js +38 -35
  45. package/dist/modules/animation/index.cjs +1 -1
  46. package/dist/modules/animation/index.js +1 -1
  47. package/dist/modules/core/clock.cjs +11 -15
  48. package/dist/modules/core/clock.d.ts +0 -2
  49. package/dist/modules/core/clock.js +11 -15
  50. package/dist/modules/core/colors.cjs +1 -1
  51. package/dist/modules/core/colors.js +1 -1
  52. package/dist/modules/core/consts.cjs +15 -1
  53. package/dist/modules/core/consts.d.ts +2 -0
  54. package/dist/modules/core/consts.js +14 -2
  55. package/dist/modules/core/globals.cjs +7 -4
  56. package/dist/modules/core/globals.d.ts +8 -2
  57. package/dist/modules/core/globals.js +8 -5
  58. package/dist/modules/core/helpers.cjs +2 -2
  59. package/dist/modules/core/helpers.js +3 -3
  60. package/dist/modules/core/render.cjs +93 -73
  61. package/dist/modules/core/render.js +96 -76
  62. package/dist/modules/core/styles.cjs +16 -2
  63. package/dist/modules/core/styles.js +16 -2
  64. package/dist/modules/core/targets.cjs +11 -13
  65. package/dist/modules/core/targets.js +11 -13
  66. package/dist/modules/core/transforms.cjs +1 -1
  67. package/dist/modules/core/transforms.js +1 -1
  68. package/dist/modules/core/units.cjs +1 -1
  69. package/dist/modules/core/units.js +1 -1
  70. package/dist/modules/core/values.cjs +73 -82
  71. package/dist/modules/core/values.d.ts +1 -2
  72. package/dist/modules/core/values.js +76 -84
  73. package/dist/modules/draggable/draggable.cjs +1 -1
  74. package/dist/modules/draggable/draggable.js +1 -1
  75. package/dist/modules/draggable/index.cjs +1 -1
  76. package/dist/modules/draggable/index.js +1 -1
  77. package/dist/modules/easings/cubic-bezier/index.cjs +1 -1
  78. package/dist/modules/easings/cubic-bezier/index.js +1 -1
  79. package/dist/modules/easings/eases/index.cjs +1 -1
  80. package/dist/modules/easings/eases/index.js +1 -1
  81. package/dist/modules/easings/eases/parser.cjs +3 -3
  82. package/dist/modules/easings/eases/parser.d.ts +4 -5
  83. package/dist/modules/easings/eases/parser.js +3 -3
  84. package/dist/modules/easings/index.cjs +1 -1
  85. package/dist/modules/easings/index.js +1 -1
  86. package/dist/modules/easings/irregular/index.cjs +1 -1
  87. package/dist/modules/easings/irregular/index.js +1 -1
  88. package/dist/modules/easings/linear/index.cjs +1 -1
  89. package/dist/modules/easings/linear/index.js +1 -1
  90. package/dist/modules/easings/none.cjs +1 -1
  91. package/dist/modules/easings/none.js +1 -1
  92. package/dist/modules/easings/spring/index.cjs +1 -1
  93. package/dist/modules/easings/spring/index.js +1 -1
  94. package/dist/modules/easings/steps/index.cjs +1 -1
  95. package/dist/modules/easings/steps/index.js +1 -1
  96. package/dist/modules/engine/engine.cjs +4 -2
  97. package/dist/modules/engine/engine.js +4 -2
  98. package/dist/modules/engine/index.cjs +1 -1
  99. package/dist/modules/engine/index.js +1 -1
  100. package/dist/modules/events/index.cjs +1 -1
  101. package/dist/modules/events/index.js +1 -1
  102. package/dist/modules/events/scroll.cjs +3 -1
  103. package/dist/modules/events/scroll.js +3 -1
  104. package/dist/modules/index.cjs +1 -1
  105. package/dist/modules/index.js +1 -1
  106. package/dist/modules/layout/index.cjs +1 -1
  107. package/dist/modules/layout/index.js +1 -1
  108. package/dist/modules/layout/layout.cjs +1 -1
  109. package/dist/modules/layout/layout.js +1 -1
  110. package/dist/modules/scope/index.cjs +1 -1
  111. package/dist/modules/scope/index.js +1 -1
  112. package/dist/modules/scope/scope.cjs +1 -1
  113. package/dist/modules/scope/scope.js +1 -1
  114. package/dist/modules/svg/drawable.cjs +1 -1
  115. package/dist/modules/svg/drawable.js +1 -1
  116. package/dist/modules/svg/helpers.cjs +1 -1
  117. package/dist/modules/svg/helpers.js +1 -1
  118. package/dist/modules/svg/index.cjs +1 -1
  119. package/dist/modules/svg/index.js +1 -1
  120. package/dist/modules/svg/morphto.cjs +1 -1
  121. package/dist/modules/svg/morphto.js +1 -1
  122. package/dist/modules/svg/motionpath.cjs +1 -1
  123. package/dist/modules/svg/motionpath.js +1 -1
  124. package/dist/modules/text/index.cjs +1 -1
  125. package/dist/modules/text/index.js +1 -1
  126. package/dist/modules/text/scramble.cjs +12 -2
  127. package/dist/modules/text/scramble.d.ts +9 -1
  128. package/dist/modules/text/scramble.js +12 -2
  129. package/dist/modules/text/split.cjs +2 -1
  130. package/dist/modules/text/split.js +2 -1
  131. package/dist/modules/timeline/index.cjs +1 -1
  132. package/dist/modules/timeline/index.js +1 -1
  133. package/dist/modules/timeline/position.cjs +1 -1
  134. package/dist/modules/timeline/position.js +1 -1
  135. package/dist/modules/timeline/timeline.cjs +14 -5
  136. package/dist/modules/timeline/timeline.d.ts +3 -3
  137. package/dist/modules/timeline/timeline.js +14 -5
  138. package/dist/modules/timer/index.cjs +1 -1
  139. package/dist/modules/timer/index.js +1 -1
  140. package/dist/modules/timer/timer.cjs +1 -1
  141. package/dist/modules/timer/timer.js +1 -1
  142. package/dist/modules/types/index.d.ts +36 -11
  143. package/dist/modules/utils/chainable.cjs +1 -1
  144. package/dist/modules/utils/chainable.js +1 -1
  145. package/dist/modules/utils/index.cjs +1 -1
  146. package/dist/modules/utils/index.js +1 -1
  147. package/dist/modules/utils/number.cjs +1 -1
  148. package/dist/modules/utils/number.js +1 -1
  149. package/dist/modules/utils/random.cjs +4 -3
  150. package/dist/modules/utils/random.d.ts +1 -1
  151. package/dist/modules/utils/random.js +4 -3
  152. package/dist/modules/utils/stagger.cjs +67 -13
  153. package/dist/modules/utils/stagger.js +69 -15
  154. package/dist/modules/utils/target.cjs +4 -1
  155. package/dist/modules/utils/target.js +4 -1
  156. package/dist/modules/utils/time.cjs +6 -5
  157. package/dist/modules/utils/time.d.ts +1 -1
  158. package/dist/modules/utils/time.js +6 -5
  159. package/dist/modules/waapi/composition.cjs +1 -1
  160. package/dist/modules/waapi/composition.js +1 -1
  161. package/dist/modules/waapi/index.cjs +1 -1
  162. package/dist/modules/waapi/index.js +1 -1
  163. package/dist/modules/waapi/waapi.cjs +1 -1
  164. package/dist/modules/waapi/waapi.js +1 -1
  165. package/package.json +38 -5
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - animation - CJS
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -11,6 +11,7 @@ var consts = require('../core/consts.cjs');
11
11
  var helpers = require('../core/helpers.cjs');
12
12
  var globals = require('../core/globals.cjs');
13
13
  var targets = require('../core/targets.cjs');
14
+ var registry = require('../adapters/registry.cjs');
14
15
  var values = require('../core/values.cjs');
15
16
  var styles = require('../core/styles.cjs');
16
17
  var units = require('../core/units.cjs');
@@ -176,6 +177,11 @@ class JSAnimation extends timer.Timer {
176
177
 
177
178
  super(/** @type {TimerParams & AnimationParams} */(parameters), parent, parentPosition);
178
179
 
180
+ /** @type {Tween} */
181
+ this._head;
182
+ /** @type {Tween} */
183
+ this._tail;
184
+
179
185
  ++JSAnimationId;
180
186
 
181
187
  const parsedTargets = targets.registerTargets(targets$1);
@@ -232,6 +238,7 @@ class JSAnimation extends timer.Timer {
232
238
  if (helpers.isKey(p)) {
233
239
 
234
240
  const tweenType = values.getTweenType(target, p);
241
+ const adapterProp = registry.resolveAdapterEntry(target, p);
235
242
 
236
243
  const propName = styles.sanitizePropertyName(p, target, tweenType);
237
244
 
@@ -315,7 +322,7 @@ class JSAnimation extends timer.Timer {
315
322
  } else {
316
323
  tweenToValue = computedToValue;
317
324
  }
318
- const tweenFromValue = values.getFunctionValue(key.from, target, ti, tl, null, prevSiblingTween);
325
+ const tweenFromValue = values.getFunctionValue(key.from, target, ti, tl, fromFunctionStore, prevSiblingTween);
319
326
  const easeToParse = key.ease || tEasing;
320
327
 
321
328
  const easeFunctionResult = values.getFunctionValue(easeToParse, target, ti, tl, null, prevSiblingTween);
@@ -333,9 +340,13 @@ class JSAnimation extends timer.Timer {
333
340
  const hasToValue = !helpers.isUnd(tweenToValue);
334
341
  const isFromToArray = helpers.isArr(tweenToValue);
335
342
  const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
343
+ // 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.
344
+ const tweenUpdateStartLocal = prevTween ? lastTweenChangeEndTime : 0;
336
345
  const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
337
346
  // Rounding is necessary here to minimize floating point errors when working in seconds
338
347
  const absoluteStartTime = helpers.round(absoluteOffsetTime + tweenStartTime, 12);
348
+ // Match the rounding pattern of prevSibling._absoluteEndTime so the composition overlap check compares cleanly when keyframes touch at a boundary.
349
+ const absoluteUpdateStartTime = helpers.round(absoluteOffsetTime + tweenUpdateStartLocal, 12);
339
350
 
340
351
  // Force a onRender callback if the animation contains at least one from value and autoplay is set to false
341
352
  if (!shouldTriggerRender && (hasFromvalue || isFromToArray)) shouldTriggerRender = 1;
@@ -344,9 +355,9 @@ class JSAnimation extends timer.Timer {
344
355
 
345
356
  if (tweenComposition !== consts.compositionTypes.none) {
346
357
  let nextSibling = siblings._head;
347
- // Iterate trough all the next siblings until we find a sibling with an equal or inferior start time
348
- while (nextSibling && !nextSibling._isOverridden && nextSibling._absoluteStartTime <= absoluteStartTime) {
349
- prevSibling = nextSibling;
358
+ // 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.
359
+ while (nextSibling && nextSibling._absoluteStartTime <= absoluteStartTime) {
360
+ if (!nextSibling._isOverridden) prevSibling = nextSibling;
350
361
  nextSibling = nextSibling._nextRep;
351
362
  // Overrides all the next siblings if the next sibling starts at the same time of after as the new tween start time
352
363
  if (nextSibling && nextSibling._absoluteStartTime >= absoluteStartTime) {
@@ -400,8 +411,8 @@ class JSAnimation extends timer.Timer {
400
411
  if (prevTween) {
401
412
  values.decomposeTweenValue(prevTween, fromTargetObject);
402
413
  } else {
403
- values.decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
404
414
  // 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
415
+ values.decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
405
416
  values.getOriginalAnimatableValue(target, propName, tweenType, inlineStylesStore), fromTargetObject);
406
417
  }
407
418
  }
@@ -440,8 +451,7 @@ class JSAnimation extends timer.Timer {
440
451
  const colorValue = fromTargetObject.t === consts.valueTypes.COLOR ? fromTargetObject : toTargetObject;
441
452
  const notColorValue = fromTargetObject.t === consts.valueTypes.COLOR ? toTargetObject : fromTargetObject;
442
453
  notColorValue.t = consts.valueTypes.COLOR;
443
- notColorValue.s = colorValue.s;
444
- notColorValue.d = [0, 0, 0, 1];
454
+ notColorValue.d = colorValue.d.map(() => 0);
445
455
  }
446
456
  }
447
457
 
@@ -471,6 +481,16 @@ class JSAnimation extends timer.Timer {
471
481
  let inlineValue = inlineStylesStore[propName];
472
482
  if (!helpers.isNil(inlineValue)) inlineStylesStore[propName] = null;
473
483
 
484
+ // Resolve the adapter setter once so render skips the lookup per frame.
485
+ const tweenSetter = adapterProp ? adapterProp.set : null;
486
+
487
+ // Rounding is necessary here to minimize floating point errors when working in seconds
488
+ lastTweenChangeEndTime = helpers.round(tweenStartTime + tweenUpdateDuration, 12);
489
+
490
+ const fromD = fromTargetObject.d;
491
+ const toD = toTargetObject.d;
492
+ const toS = toTargetObject.s;
493
+
474
494
  /** @type {Tween} */
475
495
  const tween = {
476
496
  parent: this,
@@ -481,12 +501,12 @@ class JSAnimation extends timer.Timer {
481
501
  _toFunc: toFunctionStore.func,
482
502
  _fromFunc: fromFunctionStore.func,
483
503
  _ease: parser.parseEase(tweenEasing),
484
- _fromNumbers: helpers.cloneArray(fromTargetObject.d),
485
- _toNumbers: helpers.cloneArray(toTargetObject.d),
486
- _strings: helpers.cloneArray(toTargetObject.s),
504
+ _fromNumbers: fromD ? helpers.cloneArray(fromD) : consts.emptyArray,
505
+ _toNumbers: toD ? helpers.cloneArray(toD) : consts.emptyArray,
506
+ _strings: toS ? helpers.cloneArray(toS) : consts.emptyArray,
487
507
  _fromNumber: fromTargetObject.n,
488
508
  _toNumber: toTargetObject.n,
489
- _numbers: helpers.cloneArray(fromTargetObject.d), // For additive tween and animatables
509
+ _numbers: fromD ? helpers.cloneArray(fromD) : consts.emptyArray, // For additive tween and animatables
490
510
  _number: fromTargetObject.n, // For additive tween and animatables
491
511
  _unit: toTargetObject.u,
492
512
  _modifier: tweenModifier,
@@ -496,8 +516,12 @@ class JSAnimation extends timer.Timer {
496
516
  _updateDuration: tweenUpdateDuration,
497
517
  _changeDuration: tweenUpdateDuration,
498
518
  _absoluteStartTime: absoluteStartTime,
519
+ _absoluteUpdateStartTime: absoluteUpdateStartTime,
520
+ _absoluteEndTime: helpers.round(absoluteOffsetTime + lastTweenChangeEndTime, 12),
521
+ _hasFromValue: hasFromvalue || isFromToArray ? 1 : 0,
499
522
  // NOTE: Investigate bit packing to stores ENUM / BOOL
500
523
  _tweenType: tweenType,
524
+ _setter: tweenSetter,
501
525
  _valueType: toTargetObject.t,
502
526
  _composition: tweenComposition,
503
527
  _isOverlapped: 0,
@@ -520,10 +544,11 @@ class JSAnimation extends timer.Timer {
520
544
  const vt = tween._valueType;
521
545
  if (vt === consts.valueTypes.COMPLEX) {
522
546
  tween._value = values.composeComplexValue(tween, 1, -1);
523
- } else if (vt === consts.valueTypes.COLOR) {
524
- tween._value = values.composeColorValue(tween, 1, -1);
525
547
  } else if (vt === consts.valueTypes.UNIT) {
526
548
  tween._value = `${tweenModifier(tween._toNumber)}${tween._unit}`;
549
+ } else if (vt === consts.valueTypes.COLOR) {
550
+ const d = toTargetObject.d;
551
+ tween._value = `rgba(${helpers.round(d[0], 0)},${helpers.round(d[1], 0)},${helpers.round(d[2], 0)},${d[3]})`;
527
552
  } else {
528
553
  tween._value = tweenModifier(tween._toNumber);
529
554
  }
@@ -531,8 +556,7 @@ class JSAnimation extends timer.Timer {
531
556
  if (isNaN(firstTweenChangeStartTime)) {
532
557
  firstTweenChangeStartTime = tween._startTime;
533
558
  }
534
- // Rounding is necessary here to minimize floating point errors when working in seconds
535
- lastTweenChangeEndTime = helpers.round(tweenStartTime + tweenUpdateDuration, 12);
559
+
536
560
  prevTween = tween;
537
561
  animationAnimationLength++;
538
562
 
@@ -638,8 +662,11 @@ class JSAnimation extends timer.Timer {
638
662
  tween._updateDuration = helpers.normalizeTime(tween._updateDuration * timeScale);
639
663
  tween._changeDuration = helpers.normalizeTime(tween._changeDuration * timeScale);
640
664
  tween._currentTime *= timeScale;
665
+ tween._delay *= timeScale;
641
666
  tween._startTime *= timeScale;
642
667
  tween._absoluteStartTime *= timeScale;
668
+ tween._absoluteUpdateStartTime *= timeScale;
669
+ tween._absoluteEndTime *= timeScale;
643
670
  });
644
671
  return super.stretch(newDuration);
645
672
  }
@@ -9,6 +9,10 @@ export class JSAnimation extends Timer {
9
9
  * @param {TargetsArray} [allTargets]
10
10
  */
11
11
  constructor(targets: TargetsParam, parameters: AnimationParams, parent?: Timeline, parentPosition?: number, fastSet?: boolean, index?: number, allTargets?: TargetsArray);
12
+ /** @type {Tween} */
13
+ _head: Tween;
14
+ /** @type {Tween} */
15
+ _tail: Tween;
12
16
  /** @type {TargetsArray} */
13
17
  targets: TargetsArray;
14
18
  /** @type {Callback<this>} */
@@ -42,6 +46,7 @@ export class JSAnimation extends Timer {
42
46
  }
43
47
  export function animate(targets: TargetsParam, parameters: AnimationParams): JSAnimation;
44
48
  import { Timer } from '../timer/timer.js';
49
+ import type { Tween } from '../types/index.js';
45
50
  import type { TargetsArray } from '../types/index.js';
46
51
  import type { Callback } from '../types/index.js';
47
52
  import type { EasingFunction } from '../types/index.js';
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * Anime.js - animation - ESM
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
7
7
 
8
- import { K, compositionTypes, valueTypes, minValue, isDomSymbol, tweenTypes } from '../core/consts.js';
8
+ import { K, compositionTypes, valueTypes, emptyArray, minValue, isDomSymbol, tweenTypes } from '../core/consts.js';
9
9
  import { mergeObjects, isUnd, isKey, isObj, cloneArray, isNil, round, addChild, forEachChildren, clampInfinity, normalizeTime, isArr, isNum, isFnc, isStr } from '../core/helpers.js';
10
10
  import { globals } from '../core/globals.js';
11
11
  import { registerTargets } from '../core/targets.js';
12
- import { setValue, getTweenType, getFunctionValue, decomposeRawValue, getOriginalAnimatableValue, createDecomposedValueTargetObject, decomposedOriginalValue, getRelativeValue, composeComplexValue, composeColorValue, decomposeTweenValue } from '../core/values.js';
12
+ import { resolveAdapterEntry } from '../adapters/registry.js';
13
+ import { setValue, getTweenType, getFunctionValue, decomposeRawValue, getOriginalAnimatableValue, createDecomposedValueTargetObject, decomposedOriginalValue, getRelativeValue, composeComplexValue, decomposeTweenValue } from '../core/values.js';
13
14
  import { sanitizePropertyName, revertValues } from '../core/styles.js';
14
15
  import { convertValueUnit } from '../core/units.js';
15
16
  import { parseEase } from '../easings/eases/parser.js';
@@ -174,6 +175,11 @@ class JSAnimation extends Timer {
174
175
 
175
176
  super(/** @type {TimerParams & AnimationParams} */(parameters), parent, parentPosition);
176
177
 
178
+ /** @type {Tween} */
179
+ this._head;
180
+ /** @type {Tween} */
181
+ this._tail;
182
+
177
183
  ++JSAnimationId;
178
184
 
179
185
  const parsedTargets = registerTargets(targets);
@@ -230,6 +236,7 @@ class JSAnimation extends Timer {
230
236
  if (isKey(p)) {
231
237
 
232
238
  const tweenType = getTweenType(target, p);
239
+ const adapterProp = resolveAdapterEntry(target, p);
233
240
 
234
241
  const propName = sanitizePropertyName(p, target, tweenType);
235
242
 
@@ -313,7 +320,7 @@ class JSAnimation extends Timer {
313
320
  } else {
314
321
  tweenToValue = computedToValue;
315
322
  }
316
- const tweenFromValue = getFunctionValue(key.from, target, ti, tl, null, prevSiblingTween);
323
+ const tweenFromValue = getFunctionValue(key.from, target, ti, tl, fromFunctionStore, prevSiblingTween);
317
324
  const easeToParse = key.ease || tEasing;
318
325
 
319
326
  const easeFunctionResult = getFunctionValue(easeToParse, target, ti, tl, null, prevSiblingTween);
@@ -331,9 +338,13 @@ class JSAnimation extends Timer {
331
338
  const hasToValue = !isUnd(tweenToValue);
332
339
  const isFromToArray = isArr(tweenToValue);
333
340
  const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
341
+ // 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.
342
+ const tweenUpdateStartLocal = prevTween ? lastTweenChangeEndTime : 0;
334
343
  const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
335
344
  // Rounding is necessary here to minimize floating point errors when working in seconds
336
345
  const absoluteStartTime = round(absoluteOffsetTime + tweenStartTime, 12);
346
+ // Match the rounding pattern of prevSibling._absoluteEndTime so the composition overlap check compares cleanly when keyframes touch at a boundary.
347
+ const absoluteUpdateStartTime = round(absoluteOffsetTime + tweenUpdateStartLocal, 12);
337
348
 
338
349
  // Force a onRender callback if the animation contains at least one from value and autoplay is set to false
339
350
  if (!shouldTriggerRender && (hasFromvalue || isFromToArray)) shouldTriggerRender = 1;
@@ -342,9 +353,9 @@ class JSAnimation extends Timer {
342
353
 
343
354
  if (tweenComposition !== compositionTypes.none) {
344
355
  let nextSibling = siblings._head;
345
- // Iterate trough all the next siblings until we find a sibling with an equal or inferior start time
346
- while (nextSibling && !nextSibling._isOverridden && nextSibling._absoluteStartTime <= absoluteStartTime) {
347
- prevSibling = nextSibling;
356
+ // 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.
357
+ while (nextSibling && nextSibling._absoluteStartTime <= absoluteStartTime) {
358
+ if (!nextSibling._isOverridden) prevSibling = nextSibling;
348
359
  nextSibling = nextSibling._nextRep;
349
360
  // Overrides all the next siblings if the next sibling starts at the same time of after as the new tween start time
350
361
  if (nextSibling && nextSibling._absoluteStartTime >= absoluteStartTime) {
@@ -398,8 +409,8 @@ class JSAnimation extends Timer {
398
409
  if (prevTween) {
399
410
  decomposeTweenValue(prevTween, fromTargetObject);
400
411
  } else {
401
- decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
402
412
  // 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
413
+ decomposeRawValue(parent && prevSibling && prevSibling.parent.parent === parent ? prevSibling._value :
403
414
  getOriginalAnimatableValue(target, propName, tweenType, inlineStylesStore), fromTargetObject);
404
415
  }
405
416
  }
@@ -438,8 +449,7 @@ class JSAnimation extends Timer {
438
449
  const colorValue = fromTargetObject.t === valueTypes.COLOR ? fromTargetObject : toTargetObject;
439
450
  const notColorValue = fromTargetObject.t === valueTypes.COLOR ? toTargetObject : fromTargetObject;
440
451
  notColorValue.t = valueTypes.COLOR;
441
- notColorValue.s = colorValue.s;
442
- notColorValue.d = [0, 0, 0, 1];
452
+ notColorValue.d = colorValue.d.map(() => 0);
443
453
  }
444
454
  }
445
455
 
@@ -469,6 +479,16 @@ class JSAnimation extends Timer {
469
479
  let inlineValue = inlineStylesStore[propName];
470
480
  if (!isNil(inlineValue)) inlineStylesStore[propName] = null;
471
481
 
482
+ // Resolve the adapter setter once so render skips the lookup per frame.
483
+ const tweenSetter = adapterProp ? adapterProp.set : null;
484
+
485
+ // Rounding is necessary here to minimize floating point errors when working in seconds
486
+ lastTweenChangeEndTime = round(tweenStartTime + tweenUpdateDuration, 12);
487
+
488
+ const fromD = fromTargetObject.d;
489
+ const toD = toTargetObject.d;
490
+ const toS = toTargetObject.s;
491
+
472
492
  /** @type {Tween} */
473
493
  const tween = {
474
494
  parent: this,
@@ -479,12 +499,12 @@ class JSAnimation extends Timer {
479
499
  _toFunc: toFunctionStore.func,
480
500
  _fromFunc: fromFunctionStore.func,
481
501
  _ease: parseEase(tweenEasing),
482
- _fromNumbers: cloneArray(fromTargetObject.d),
483
- _toNumbers: cloneArray(toTargetObject.d),
484
- _strings: cloneArray(toTargetObject.s),
502
+ _fromNumbers: fromD ? cloneArray(fromD) : emptyArray,
503
+ _toNumbers: toD ? cloneArray(toD) : emptyArray,
504
+ _strings: toS ? cloneArray(toS) : emptyArray,
485
505
  _fromNumber: fromTargetObject.n,
486
506
  _toNumber: toTargetObject.n,
487
- _numbers: cloneArray(fromTargetObject.d), // For additive tween and animatables
507
+ _numbers: fromD ? cloneArray(fromD) : emptyArray, // For additive tween and animatables
488
508
  _number: fromTargetObject.n, // For additive tween and animatables
489
509
  _unit: toTargetObject.u,
490
510
  _modifier: tweenModifier,
@@ -494,8 +514,12 @@ class JSAnimation extends Timer {
494
514
  _updateDuration: tweenUpdateDuration,
495
515
  _changeDuration: tweenUpdateDuration,
496
516
  _absoluteStartTime: absoluteStartTime,
517
+ _absoluteUpdateStartTime: absoluteUpdateStartTime,
518
+ _absoluteEndTime: round(absoluteOffsetTime + lastTweenChangeEndTime, 12),
519
+ _hasFromValue: hasFromvalue || isFromToArray ? 1 : 0,
497
520
  // NOTE: Investigate bit packing to stores ENUM / BOOL
498
521
  _tweenType: tweenType,
522
+ _setter: tweenSetter,
499
523
  _valueType: toTargetObject.t,
500
524
  _composition: tweenComposition,
501
525
  _isOverlapped: 0,
@@ -518,10 +542,11 @@ class JSAnimation extends Timer {
518
542
  const vt = tween._valueType;
519
543
  if (vt === valueTypes.COMPLEX) {
520
544
  tween._value = composeComplexValue(tween, 1, -1);
521
- } else if (vt === valueTypes.COLOR) {
522
- tween._value = composeColorValue(tween, 1, -1);
523
545
  } else if (vt === valueTypes.UNIT) {
524
546
  tween._value = `${tweenModifier(tween._toNumber)}${tween._unit}`;
547
+ } else if (vt === valueTypes.COLOR) {
548
+ const d = toTargetObject.d;
549
+ tween._value = `rgba(${round(d[0], 0)},${round(d[1], 0)},${round(d[2], 0)},${d[3]})`;
525
550
  } else {
526
551
  tween._value = tweenModifier(tween._toNumber);
527
552
  }
@@ -529,8 +554,7 @@ class JSAnimation extends Timer {
529
554
  if (isNaN(firstTweenChangeStartTime)) {
530
555
  firstTweenChangeStartTime = tween._startTime;
531
556
  }
532
- // Rounding is necessary here to minimize floating point errors when working in seconds
533
- lastTweenChangeEndTime = round(tweenStartTime + tweenUpdateDuration, 12);
557
+
534
558
  prevTween = tween;
535
559
  animationAnimationLength++;
536
560
 
@@ -636,8 +660,11 @@ class JSAnimation extends Timer {
636
660
  tween._updateDuration = normalizeTime(tween._updateDuration * timeScale);
637
661
  tween._changeDuration = normalizeTime(tween._changeDuration * timeScale);
638
662
  tween._currentTime *= timeScale;
663
+ tween._delay *= timeScale;
639
664
  tween._startTime *= timeScale;
640
665
  tween._absoluteStartTime *= timeScale;
666
+ tween._absoluteUpdateStartTime *= timeScale;
667
+ tween._absoluteEndTime *= timeScale;
641
668
  });
642
669
  return super.stretch(newDuration);
643
670
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - animation - CJS
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -98,7 +98,7 @@ const composeTween = (tween, siblings) => {
98
98
  if (prevSibling) {
99
99
 
100
100
  const prevParent = prevSibling.parent;
101
- const prevAbsEndTime = prevSibling._absoluteStartTime + prevSibling._changeDuration;
101
+ const prevAbsEndTime = prevSibling._absoluteEndTime;
102
102
 
103
103
  // Handle looped animations tween
104
104
 
@@ -124,7 +124,8 @@ const composeTween = (tween, siblings) => {
124
124
 
125
125
  }
126
126
 
127
- const absoluteUpdateStartTime = tweenAbsStartTime - tween._delay;
127
+ // 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.
128
+ const absoluteUpdateStartTime = tween._absoluteUpdateStartTime;
128
129
 
129
130
  if (prevAbsEndTime > absoluteUpdateStartTime) {
130
131
 
@@ -144,37 +145,41 @@ const composeTween = (tween, siblings) => {
144
145
  }
145
146
  }
146
147
 
147
- // Pause (and cancel) the parent if it only contains overlapped tweens
148
+ // Skip the cancel cascade when both tweens share the same parent timeline, a timeline cannot replace itself.
149
+ const tweenParentTL = tween.parent.parent;
150
+ if (!tweenParentTL || tweenParentTL !== prevParent.parent) {
148
151
 
149
- let pausePrevParentAnimation = true;
152
+ let pausePrevParentAnimation = true;
150
153
 
151
- helpers.forEachChildren(prevParent, (/** @type Tween */t) => {
152
- if (!t._isOverlapped) pausePrevParentAnimation = false;
153
- });
154
+ helpers.forEachChildren(prevParent, (/** @type Tween */t) => {
155
+ if (!t._isOverlapped) pausePrevParentAnimation = false;
156
+ });
154
157
 
155
- if (pausePrevParentAnimation) {
156
- const prevParentTL = prevParent.parent;
157
- if (prevParentTL) {
158
- let pausePrevParentTL = true;
159
- helpers.forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
160
- if (a !== prevParent) {
161
- helpers.forEachChildren(a, (/** @type Tween */t) => {
162
- if (!t._isOverlapped) pausePrevParentTL = false;
163
- });
158
+ if (pausePrevParentAnimation) {
159
+ const prevParentTL = prevParent.parent;
160
+ if (prevParentTL) {
161
+ let pausePrevParentTL = true;
162
+ helpers.forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
163
+ if (a !== prevParent) {
164
+ helpers.forEachChildren(a, (/** @type Tween */t) => {
165
+ if (!t._isOverlapped) pausePrevParentTL = false;
166
+ });
167
+ }
168
+ });
169
+ if (pausePrevParentTL) {
170
+ prevParentTL.cancel();
164
171
  }
165
- });
166
- if (pausePrevParentTL) {
167
- prevParentTL.cancel();
172
+ } else {
173
+ prevParent.cancel();
174
+ // Previously, calling .cancel() on a timeline child would affect the render order of other children
175
+ // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
176
+ // This is no longer needed since timeline tween composition is now handled separately
177
+ // Keeping this here for reference
178
+ // prevParent.completed = true;
179
+ // prevParent.pause();
168
180
  }
169
- } else {
170
- prevParent.cancel();
171
- // Previously, calling .cancel() on a timeline child would affect the render order of other children
172
- // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
173
- // This is no longer needed since timeline tween composition is now handled separately
174
- // Keeping this here for reference
175
- // prevParent.completed = true;
176
- // prevParent.pause();
177
181
  }
182
+
178
183
  }
179
184
 
180
185
  }
@@ -229,14 +234,12 @@ const composeTween = (tween, siblings) => {
229
234
  tween._number = 0;
230
235
  lookupTween._fromNumber = toNumber;
231
236
 
232
- if (tween._toNumbers) {
237
+ if (tween._toNumbers.length) {
233
238
  const toNumbers = helpers.cloneArray(tween._toNumbers);
234
- if (toNumbers) {
235
- toNumbers.forEach((value, i) => {
236
- tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
237
- tween._toNumbers[i] = 0;
238
- });
239
- }
239
+ toNumbers.forEach((value, i) => {
240
+ tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
241
+ tween._toNumbers[i] = 0;
242
+ });
240
243
  lookupTween._fromNumbers = toNumbers;
241
244
  }
242
245
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - animation - ESM
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -96,7 +96,7 @@ const composeTween = (tween, siblings) => {
96
96
  if (prevSibling) {
97
97
 
98
98
  const prevParent = prevSibling.parent;
99
- const prevAbsEndTime = prevSibling._absoluteStartTime + prevSibling._changeDuration;
99
+ const prevAbsEndTime = prevSibling._absoluteEndTime;
100
100
 
101
101
  // Handle looped animations tween
102
102
 
@@ -122,7 +122,8 @@ const composeTween = (tween, siblings) => {
122
122
 
123
123
  }
124
124
 
125
- const absoluteUpdateStartTime = tweenAbsStartTime - tween._delay;
125
+ // 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.
126
+ const absoluteUpdateStartTime = tween._absoluteUpdateStartTime;
126
127
 
127
128
  if (prevAbsEndTime > absoluteUpdateStartTime) {
128
129
 
@@ -142,37 +143,41 @@ const composeTween = (tween, siblings) => {
142
143
  }
143
144
  }
144
145
 
145
- // Pause (and cancel) the parent if it only contains overlapped tweens
146
+ // Skip the cancel cascade when both tweens share the same parent timeline, a timeline cannot replace itself.
147
+ const tweenParentTL = tween.parent.parent;
148
+ if (!tweenParentTL || tweenParentTL !== prevParent.parent) {
146
149
 
147
- let pausePrevParentAnimation = true;
150
+ let pausePrevParentAnimation = true;
148
151
 
149
- forEachChildren(prevParent, (/** @type Tween */t) => {
150
- if (!t._isOverlapped) pausePrevParentAnimation = false;
151
- });
152
+ forEachChildren(prevParent, (/** @type Tween */t) => {
153
+ if (!t._isOverlapped) pausePrevParentAnimation = false;
154
+ });
152
155
 
153
- if (pausePrevParentAnimation) {
154
- const prevParentTL = prevParent.parent;
155
- if (prevParentTL) {
156
- let pausePrevParentTL = true;
157
- forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
158
- if (a !== prevParent) {
159
- forEachChildren(a, (/** @type Tween */t) => {
160
- if (!t._isOverlapped) pausePrevParentTL = false;
161
- });
156
+ if (pausePrevParentAnimation) {
157
+ const prevParentTL = prevParent.parent;
158
+ if (prevParentTL) {
159
+ let pausePrevParentTL = true;
160
+ forEachChildren(prevParentTL, (/** @type JSAnimation */a) => {
161
+ if (a !== prevParent) {
162
+ forEachChildren(a, (/** @type Tween */t) => {
163
+ if (!t._isOverlapped) pausePrevParentTL = false;
164
+ });
165
+ }
166
+ });
167
+ if (pausePrevParentTL) {
168
+ prevParentTL.cancel();
162
169
  }
163
- });
164
- if (pausePrevParentTL) {
165
- prevParentTL.cancel();
170
+ } else {
171
+ prevParent.cancel();
172
+ // Previously, calling .cancel() on a timeline child would affect the render order of other children
173
+ // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
174
+ // This is no longer needed since timeline tween composition is now handled separately
175
+ // Keeping this here for reference
176
+ // prevParent.completed = true;
177
+ // prevParent.pause();
166
178
  }
167
- } else {
168
- prevParent.cancel();
169
- // Previously, calling .cancel() on a timeline child would affect the render order of other children
170
- // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
171
- // This is no longer needed since timeline tween composition is now handled separately
172
- // Keeping this here for reference
173
- // prevParent.completed = true;
174
- // prevParent.pause();
175
179
  }
180
+
176
181
  }
177
182
 
178
183
  }
@@ -227,14 +232,12 @@ const composeTween = (tween, siblings) => {
227
232
  tween._number = 0;
228
233
  lookupTween._fromNumber = toNumber;
229
234
 
230
- if (tween._toNumbers) {
235
+ if (tween._toNumbers.length) {
231
236
  const toNumbers = cloneArray(tween._toNumbers);
232
- if (toNumbers) {
233
- toNumbers.forEach((value, i) => {
234
- tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
235
- tween._toNumbers[i] = 0;
236
- });
237
- }
237
+ toNumbers.forEach((value, i) => {
238
+ tween._fromNumbers[i] = lookupTween._fromNumbers[i] - value;
239
+ tween._toNumbers[i] = 0;
240
+ });
238
241
  lookupTween._fromNumbers = toNumbers;
239
242
  }
240
243
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - animation - CJS
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - animation - ESM
3
- * @version v4.4.0
3
+ * @version v4.5.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */