animejs 4.0.0 → 4.0.2

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/lib/anime.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * anime.js - ESM
3
- * @version v4.0.0
3
+ * @version v4.0.2
4
4
  * @author Julian Garnier
5
5
  * @license MIT
6
6
  * @copyright (c) 2025 Julian Garnier
@@ -9,18 +9,18 @@
9
9
 
10
10
  /**
11
11
  * @typedef {Object} DefaultsParams
12
- * @property {number|string} [id]
12
+ * @property {Number|String} [id]
13
13
  * @property {PercentageKeyframes|DurationKeyframes} [keyframes]
14
14
  * @property {EasingParam} [playbackEase]
15
- * @property {number} [playbackRate]
16
- * @property {number} [frameRate]
17
- * @property {number|boolean} [loop]
18
- * @property {boolean} [reversed]
19
- * @property {boolean} [alternate]
20
- * @property {boolean|ScrollObserver} [autoplay]
21
- * @property {number|FunctionValue} [duration]
22
- * @property {number|FunctionValue} [delay]
23
- * @property {number} [loopDelay]
15
+ * @property {Number} [playbackRate]
16
+ * @property {Number} [frameRate]
17
+ * @property {Number|Boolean} [loop]
18
+ * @property {Boolean} [reversed]
19
+ * @property {Boolean} [alternate]
20
+ * @property {Boolean|ScrollObserver} [autoplay]
21
+ * @property {Number|FunctionValue} [duration]
22
+ * @property {Number|FunctionValue} [delay]
23
+ * @property {Number} [loopDelay]
24
24
  * @property {EasingParam} [ease]
25
25
  * @property {'none'|'replace'|'blend'|compositionTypes} [composition]
26
26
  * @property {(v: any) => any} [modifier]
@@ -38,6 +38,60 @@
38
38
  /** @typedef {Timer&JSAnimation&Timeline} CallbackArgument */
39
39
  /** @typedef {Animatable|Tickable|Draggable|ScrollObserver|Scope} Revertible */
40
40
 
41
+ /**
42
+ * @typedef {Object} DraggableAxisParam
43
+ * @property {String} [mapTo]
44
+ * @property {TweenModifier} [modifier]
45
+ * @property {TweenComposition} [composition]
46
+ * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
47
+ */
48
+
49
+ /**
50
+ * @typedef {Object} DraggableCursorParams
51
+ * @property {String} [onHover]
52
+ * @property {String} [onGrab]
53
+ */
54
+
55
+ /**
56
+ * @typedef {Object} DraggableParams
57
+ * @property {DOMTargetSelector} [trigger]
58
+ * @property {DOMTargetSelector|Array<Number>|((draggable: Draggable) => DOMTargetSelector|Array<Number>)} [container]
59
+ * @property {Boolean|DraggableAxisParam} [x]
60
+ * @property {Boolean|DraggableAxisParam} [y]
61
+ * @property {TweenModifier} [modifier]
62
+ * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
63
+ * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [containerPadding]
64
+ * @property {Number|((draggable: Draggable) => Number)} [containerFriction]
65
+ * @property {Number|((draggable: Draggable) => Number)} [releaseContainerFriction]
66
+ * @property {Number|((draggable: Draggable) => Number)} [dragSpeed]
67
+ * @property {Number|((draggable: Draggable) => Number)} [scrollSpeed]
68
+ * @property {Number|((draggable: Draggable) => Number)} [scrollThreshold]
69
+ * @property {Number|((draggable: Draggable) => Number)} [minVelocity]
70
+ * @property {Number|((draggable: Draggable) => Number)} [maxVelocity]
71
+ * @property {Number|((draggable: Draggable) => Number)} [velocityMultiplier]
72
+ * @property {Number} [releaseMass]
73
+ * @property {Number} [releaseStiffness]
74
+ * @property {Number} [releaseDamping]
75
+ * @property {Boolean} [releaseDamping]
76
+ * @property {EasingParam} [releaseEase]
77
+ * @property {Boolean|DraggableCursorParams|((draggable: Draggable) => Boolean|DraggableCursorParams)} [cursor]
78
+ * @property {Callback<Draggable>} [onGrab]
79
+ * @property {Callback<Draggable>} [onDrag]
80
+ * @property {Callback<Draggable>} [onRelease]
81
+ * @property {Callback<Draggable>} [onUpdate]
82
+ * @property {Callback<Draggable>} [onSettle]
83
+ * @property {Callback<Draggable>} [onSnap]
84
+ * @property {Callback<Draggable>} [onResize]
85
+ * @property {Callback<Draggable>} [onAfterResize]
86
+ */
87
+
88
+ /**
89
+ * @typedef {SVGGeometryElement & {
90
+ * setAttribute(name: 'draw', value: `${number} ${number}`): void;
91
+ * draw: `${number} ${number}`;
92
+ * }} DrawableSVGGeometry
93
+ */
94
+
41
95
  /**
42
96
  * @callback EasingFunction
43
97
  * @param {Number} time
@@ -450,7 +504,7 @@ const globals = {
450
504
  tickThreshold: 200,
451
505
  };
452
506
 
453
- const globalVersions = { version: '4.0.0', engine: null };
507
+ const globalVersions = { version: '4.0.2', engine: null };
454
508
 
455
509
  if (isBrowser) {
456
510
  if (!win.AnimeJS) win.AnimeJS = [];
@@ -531,7 +585,6 @@ const atan2 = Math.atan2;
531
585
  const PI = Math.PI;
532
586
  const _round = Math.round;
533
587
 
534
-
535
588
  /**
536
589
  * @param {Number} v
537
590
  * @param {Number} min
@@ -580,7 +633,7 @@ const clampInfinity = v => v === Infinity ? maxValue : v === -Infinity ? -1e12 :
580
633
  * @param {Number} v
581
634
  * @return {Number}
582
635
  */
583
- const clampZero = v => v < minValue ? minValue : v;
636
+ const normalizeTime = v => v <= minValue ? minValue : clampInfinity(round(v, 11));
584
637
 
585
638
  // Arrays
586
639
 
@@ -1504,43 +1557,61 @@ const morphTo = (path2, precision = .33) => ($path1) => {
1504
1557
  };
1505
1558
 
1506
1559
  /**
1507
- * @param {SVGGeometryElement} $el
1508
- * @param {Number} start
1509
- * @param {Number} end
1510
- * @return {Proxy}
1560
+ * @param {SVGGeometryElement} [$el]
1561
+ * @return {Number}
1511
1562
  */
1512
- function createDrawableProxy($el, start, end) {
1513
- const strokeLineCap = getComputedStyle($el).strokeLinecap;
1563
+ const getScaleFactor = $el => {
1564
+ let scaleFactor = 1;
1565
+ if ($el && $el.getCTM) {
1566
+ const ctm = $el.getCTM();
1567
+ if (ctm) {
1568
+ const scaleX = sqrt(ctm.a * ctm.a + ctm.b * ctm.b);
1569
+ const scaleY = sqrt(ctm.c * ctm.c + ctm.d * ctm.d);
1570
+ scaleFactor = (scaleX + scaleY) / 2;
1571
+ }
1572
+ }
1573
+ return scaleFactor;
1574
+ };
1575
+
1576
+ /**
1577
+ * Creates a proxy that wraps an SVGGeometryElement and adds drawing functionality.
1578
+ * @param {SVGGeometryElement} $el - The SVG element to transform into a drawable
1579
+ * @param {number} start - Starting position (0-1)
1580
+ * @param {number} end - Ending position (0-1)
1581
+ * @return {DrawableSVGGeometry} - Returns a proxy that preserves the original element's type with additional 'draw' attribute functionality
1582
+ */
1583
+ const createDrawableProxy = ($el, start, end) => {
1514
1584
  const pathLength = K;
1585
+ const computedStyles = getComputedStyle($el);
1586
+ const strokeLineCap = computedStyles.strokeLinecap;
1587
+ // @ts-ignore
1588
+ const $scalled = computedStyles.vectorEffect === 'non-scaling-stroke' ? $el : null;
1515
1589
  let currentCap = strokeLineCap;
1590
+
1516
1591
  const proxy = new Proxy($el, {
1517
1592
  get(target, property) {
1518
1593
  const value = target[property];
1519
1594
  if (property === proxyTargetSymbol) return target;
1520
1595
  if (property === 'setAttribute') {
1521
- /** @param {any[]} args */
1522
1596
  return (...args) => {
1523
1597
  if (args[0] === 'draw') {
1524
1598
  const value = args[1];
1525
1599
  const values = value.split(' ');
1526
1600
  const v1 = +values[0];
1527
1601
  const v2 = +values[1];
1528
-
1529
1602
  // TOTO: Benchmark if performing two slices is more performant than one split
1530
-
1531
1603
  // const spaceIndex = value.indexOf(' ');
1532
1604
  // const v1 = round(+value.slice(0, spaceIndex), precision);
1533
1605
  // const v2 = round(+value.slice(spaceIndex + 1), precision);
1534
-
1535
- const os = v1 * -1e3;
1536
- const d1 = (v2 * pathLength) + os;
1537
- // Prevents linecap to smear by offsetting the dasharray length by 0.01% when v2 is not at max
1538
- const d2 = (pathLength + ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10) - d1);
1539
- // Handle cases where the cap is still visible when the line is completly hidden
1606
+ const scaleFactor = getScaleFactor($scalled);
1607
+ const os = v1 * -1e3 * scaleFactor;
1608
+ const d1 = (v2 * pathLength * scaleFactor) + os;
1609
+ const d2 = (pathLength * scaleFactor +
1610
+ ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10 * scaleFactor) - d1);
1540
1611
  if (strokeLineCap !== 'butt') {
1541
1612
  const newCap = v1 === v2 ? 'butt' : strokeLineCap;
1542
1613
  if (currentCap !== newCap) {
1543
- target.setAttribute('stroke-linecap', `${newCap}`);
1614
+ target.style.strokeLinecap = `${newCap}`;
1544
1615
  currentCap = newCap;
1545
1616
  }
1546
1617
  }
@@ -1550,31 +1621,37 @@ function createDrawableProxy($el, start, end) {
1550
1621
  return Reflect.apply(value, target, args);
1551
1622
  };
1552
1623
  }
1624
+
1553
1625
  if (isFnc(value)) {
1554
- /** @param {any[]} args */
1555
1626
  return (...args) => Reflect.apply(value, target, args);
1556
1627
  } else {
1557
1628
  return value;
1558
1629
  }
1559
1630
  }
1560
1631
  });
1632
+
1561
1633
  if ($el.getAttribute('pathLength') !== `${pathLength}`) {
1562
1634
  $el.setAttribute('pathLength', `${pathLength}`);
1563
1635
  proxy.setAttribute('draw', `${start} ${end}`);
1564
1636
  }
1565
- return /** @type {typeof Proxy} */(/** @type {unknown} */(proxy));
1566
- }
1637
+
1638
+ return /** @type {DrawableSVGGeometry} */(proxy);
1639
+ };
1567
1640
 
1568
1641
  /**
1569
- * @param {TargetsParam} selector
1570
- * @param {Number} [start=0]
1571
- * @param {Number} [end=0]
1572
- * @return {Array.<Proxy>}
1642
+ * Creates drawable proxies for multiple SVG elements.
1643
+ * @param {TargetsParam} selector - CSS selector, SVG element, or array of elements and selectors
1644
+ * @param {number} [start=0] - Starting position (0-1)
1645
+ * @param {number} [end=0] - Ending position (0-1)
1646
+ * @return {Array<DrawableSVGGeometry>} - Array of proxied elements with drawing functionality
1573
1647
  */
1574
1648
  const createDrawable = (selector, start = 0, end = 0) => {
1575
- const els = /** @type {Array.<Proxy>} */((/** @type {unknown} */(parseTargets(selector))));
1576
- els.forEach(($el, i) => els[i] = createDrawableProxy(/** @type {SVGGeometryElement} */(/** @type {unknown} */($el)), start, end));
1577
- return els;
1649
+ const els = parseTargets(selector);
1650
+ return els.map($el => createDrawableProxy(
1651
+ /** @type {SVGGeometryElement} */($el),
1652
+ start,
1653
+ end
1654
+ ));
1578
1655
  };
1579
1656
 
1580
1657
  // Motion path animation
@@ -2589,11 +2666,12 @@ class Timer extends Clock {
2589
2666
  */
2590
2667
  stretch(newDuration) {
2591
2668
  const currentDuration = this.duration;
2592
- if (currentDuration === clampZero(newDuration)) return this;
2669
+ const normlizedDuration = normalizeTime(newDuration);
2670
+ if (currentDuration === normlizedDuration) return this;
2593
2671
  const timeScale = newDuration / currentDuration;
2594
2672
  const isSetter = newDuration <= minValue;
2595
- this.duration = isSetter ? minValue : clampZero(clampInfinity(round(currentDuration * timeScale, 12)));
2596
- this.iterationDuration = isSetter ? minValue : clampZero(clampInfinity(round(this.iterationDuration * timeScale, 12)));
2673
+ this.duration = isSetter ? minValue : normlizedDuration;
2674
+ this.iterationDuration = isSetter ? minValue : normalizeTime(this.iterationDuration * timeScale);
2597
2675
  this._offset *= timeScale;
2598
2676
  this._delay *= timeScale;
2599
2677
  this._loopDelay *= timeScale;
@@ -3637,13 +3715,13 @@ class JSAnimation extends Timer {
3637
3715
  */
3638
3716
  stretch(newDuration) {
3639
3717
  const currentDuration = this.duration;
3640
- if (currentDuration === clampZero(newDuration)) return this;
3718
+ if (currentDuration === normalizeTime(newDuration)) return this;
3641
3719
  const timeScale = newDuration / currentDuration;
3642
3720
  // NOTE: Find a better way to handle the stretch of an animation after stretch = 0
3643
3721
  forEachChildren(this, (/** @type {Tween} */tween) => {
3644
3722
  // Rounding is necessary here to minimize floating point errors
3645
- tween._updateDuration = clampZero(round(tween._updateDuration * timeScale, 12));
3646
- tween._changeDuration = clampZero(round(tween._changeDuration * timeScale, 12));
3723
+ tween._updateDuration = normalizeTime(tween._updateDuration * timeScale);
3724
+ tween._changeDuration = normalizeTime(tween._changeDuration * timeScale);
3647
3725
  tween._currentTime *= timeScale;
3648
3726
  tween._startTime *= timeScale;
3649
3727
  tween._absoluteStartTime *= timeScale;
@@ -3745,13 +3823,14 @@ const parseWAAPIEasing = (ease) => {
3745
3823
  const parsed = parseEaseString(ease, WAAPIeases, WAAPIEasesLookups);
3746
3824
  if (isFnc(parsed)) parsedEase = parsed === none ? 'linear' : easingToLinear(parsed);
3747
3825
  }
3826
+ WAAPIEasesLookups[ease] = parsedEase;
3748
3827
  } else if (isFnc(ease)) {
3749
3828
  const easing = easingToLinear(ease);
3750
3829
  if (easing) parsedEase = easing;
3751
3830
  } else if (/** @type {Spring} */(ease).ease) {
3752
3831
  parsedEase = easingToLinear(/** @type {Spring} */(ease).ease);
3753
3832
  }
3754
- return WAAPIEasesLookups[ease] = parsedEase;
3833
+ return parsedEase;
3755
3834
  };
3756
3835
 
3757
3836
  /**
@@ -3825,6 +3904,7 @@ const validIndividualTransforms = [...transformsShorthands, ...validTransforms.f
3825
3904
  let transformsPropertiesRegistered = isBrowser && (isUnd(CSS) || !Object.hasOwnProperty.call(CSS, 'registerProperty'));
3826
3905
 
3827
3906
  const registerTransformsProperties = () => {
3907
+ if (transformsPropertiesRegistered) return;
3828
3908
  validTransforms.forEach(t => {
3829
3909
  const isSkew = stringStartsWith(t, 'skew');
3830
3910
  const isScale = stringStartsWith(t, 'scale');
@@ -3832,13 +3912,14 @@ const registerTransformsProperties = () => {
3832
3912
  const isTranslate = stringStartsWith(t, 'translate');
3833
3913
  const isAngle = isRotate || isSkew;
3834
3914
  const syntax = isAngle ? '<angle>' : isScale ? "<number>" : isTranslate ? "<length-percentage>" : "*";
3835
- CSS.registerProperty({
3836
- name: '--' + t,
3837
- syntax,
3838
- inherits: false,
3839
- initialValue: isTranslate ? '0px' : isAngle ? '0deg' : isScale ? '1' : '0',
3840
- });
3841
- });
3915
+ try {
3916
+ CSS.registerProperty({
3917
+ name: '--' + t,
3918
+ syntax,
3919
+ inherits: false,
3920
+ initialValue: isTranslate ? '0px' : isAngle ? '0deg' : isScale ? '1' : '0',
3921
+ });
3922
+ } catch {} });
3842
3923
  transformsPropertiesRegistered = true;
3843
3924
  };
3844
3925
 
@@ -3953,7 +4034,7 @@ class WAAPIAnimation {
3953
4034
 
3954
4035
  if (globals.scope) globals.scope.revertibles.push(this);
3955
4036
 
3956
- if (!transformsPropertiesRegistered) registerTransformsProperties();
4037
+ registerTransformsProperties();
3957
4038
 
3958
4039
  const parsedTargets = registerTargets(targets);
3959
4040
  const targetsLength = parsedTargets.length;
@@ -4120,7 +4201,13 @@ class WAAPIAnimation {
4120
4201
  /** @param {Number} time */
4121
4202
  set currentTime(time) {
4122
4203
  const t = time * (globals.timeScale === 1 ? 1 : K);
4123
- this.forEach(anim => anim.currentTime = t);
4204
+ this.forEach(anim => {
4205
+ // Make sure the animation playState is not 'paused' in order to properly trigger an onfinish callback.
4206
+ // The "paused" play state supersedes the "finished" play state; if the animation is both paused and finished, the "paused" state is the one that will be reported.
4207
+ // https://developer.mozilla.org/en-US/docs/Web/API/Animation/finish_event
4208
+ if (t >= this.duration) anim.play();
4209
+ anim.currentTime = t;
4210
+ });
4124
4211
  }
4125
4212
 
4126
4213
  get progress() {
@@ -4907,15 +4994,11 @@ class Timeline extends Timer {
4907
4994
  */
4908
4995
  stretch(newDuration) {
4909
4996
  const currentDuration = this.duration;
4910
- if (currentDuration === clampZero(newDuration)) return this;
4997
+ if (currentDuration === normalizeTime(newDuration)) return this;
4911
4998
  const timeScale = newDuration / currentDuration;
4912
4999
  const labels = this.labels;
4913
- forEachChildren(this, (/** @type {JSAnimation} */child) => {
4914
- child.stretch(child.duration * timeScale);
4915
- });
4916
- for (let labelName in labels) {
4917
- labels[labelName] *= timeScale;
4918
- }
5000
+ forEachChildren(this, (/** @type {JSAnimation} */child) => child.stretch(child.duration * timeScale));
5001
+ for (let labelName in labels) labels[labelName] *= timeScale;
4919
5002
  return super.stretch(newDuration);
4920
5003
  }
4921
5004
 
@@ -5281,12 +5364,6 @@ class Transforms {
5281
5364
  }
5282
5365
  }
5283
5366
 
5284
- /**
5285
- * @typedef {Object} DraggableCursorParams
5286
- * @property {String} [onHover]
5287
- * @property {String} [onGrab]
5288
- */
5289
-
5290
5367
  /**
5291
5368
  * @template {Array<Number>|DOMTargetSelector|String|Number|Boolean|Function|DraggableCursorParams} T
5292
5369
  * @param {T | ((draggable: Draggable) => T)} value
@@ -5297,47 +5374,6 @@ const parseDraggableFunctionParameter = (value, draggable) => value && isFnc(val
5297
5374
 
5298
5375
  let zIndex = 0;
5299
5376
 
5300
- /**
5301
- * @typedef {Object} DraggableAxisParam
5302
- * @property {String} [mapTo]
5303
- * @property {TweenModifier} [modifier]
5304
- * @property {TweenComposition} [composition]
5305
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
5306
- */
5307
-
5308
- /**
5309
- * @typedef {Object} DraggableParams
5310
- * @property {DOMTargetSelector} [trigger]
5311
- * @property {DOMTargetSelector|Array<Number>|((draggable: Draggable) => DOMTargetSelector|Array<Number>)} [container]
5312
- * @property {Boolean|DraggableAxisParam} [x]
5313
- * @property {Boolean|DraggableAxisParam} [y]
5314
- * @property {TweenModifier} [modifier]
5315
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
5316
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [containerPadding]
5317
- * @property {Number|((draggable: Draggable) => Number)} [containerFriction]
5318
- * @property {Number|((draggable: Draggable) => Number)} [releaseContainerFriction]
5319
- * @property {Number|((draggable: Draggable) => Number)} [dragSpeed]
5320
- * @property {Number|((draggable: Draggable) => Number)} [scrollSpeed]
5321
- * @property {Number|((draggable: Draggable) => Number)} [scrollThreshold]
5322
- * @property {Number|((draggable: Draggable) => Number)} [minVelocity]
5323
- * @property {Number|((draggable: Draggable) => Number)} [maxVelocity]
5324
- * @property {Number|((draggable: Draggable) => Number)} [velocityMultiplier]
5325
- * @property {Number} [releaseMass]
5326
- * @property {Number} [releaseStiffness]
5327
- * @property {Number} [releaseDamping]
5328
- * @property {Boolean} [releaseDamping]
5329
- * @property {EasingParam} [releaseEase]
5330
- * @property {Boolean|DraggableCursorParams|((draggable: Draggable) => Boolean|DraggableCursorParams)} [cursor]
5331
- * @property {Callback<Draggable>} [onGrab]
5332
- * @property {Callback<Draggable>} [onDrag]
5333
- * @property {Callback<Draggable>} [onRelease]
5334
- * @property {Callback<Draggable>} [onUpdate]
5335
- * @property {Callback<Draggable>} [onSettle]
5336
- * @property {Callback<Draggable>} [onSnap]
5337
- * @property {Callback<Draggable>} [onResize]
5338
- * @property {Callback<Draggable>} [onAfterResize]
5339
- */
5340
-
5341
5377
  class Draggable {
5342
5378
  /**
5343
5379
  * @param {TargetsParam} target
@@ -5536,7 +5572,7 @@ class Draggable {
5536
5572
  this.canScroll = false;
5537
5573
  this.enabled = false;
5538
5574
  this.initialized = false;
5539
- this.activeProp = this.disabled[0] ? yProp : xProp;
5575
+ this.activeProp = this.disabled[1] ? xProp : yProp;
5540
5576
  this.animate.animations[this.activeProp].onRender = () => {
5541
5577
  const hasUpdated = this.updated;
5542
5578
  const hasMoved = this.grabbed && hasUpdated;
@@ -6356,6 +6392,7 @@ class Draggable {
6356
6392
  this.overshootXTicker.revert();
6357
6393
  this.overshootYTicker.revert();
6358
6394
  this.resizeTicker.revert();
6395
+ this.animate.revert();
6359
6396
  return this;
6360
6397
  }
6361
6398
 
@@ -6407,7 +6444,7 @@ const createDraggable = (target, parameters) => new Draggable(target, parameters
6407
6444
 
6408
6445
  /**
6409
6446
  * @typedef {Object} ReactRef
6410
- * @property {HTMLElement|SVGElement} [current]
6447
+ * @property {HTMLElement|SVGElement|null} [current]
6411
6448
  */
6412
6449
 
6413
6450
  /**