animejs 4.0.1 → 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/types/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * anime.js - ESM
3
- * @version v4.0.1
3
+ * @version v4.0.2
4
4
  * @author Julian Garnier
5
5
  * @license MIT
6
6
  * @copyright (c) 2025 Julian Garnier
@@ -137,7 +137,7 @@ const globals = {
137
137
  /** @type {Number} */
138
138
  tickThreshold: 200,
139
139
  };
140
- const globalVersions = { version: '4.0.1', engine: null };
140
+ const globalVersions = { version: '4.0.2', engine: null };
141
141
  if (isBrowser) {
142
142
  if (!win.AnimeJS)
143
143
  win.AnimeJS = [];
@@ -253,7 +253,7 @@ const clampInfinity = v => v === Infinity ? maxValue : v === -Infinity ? -1e12 :
253
253
  * @param {Number} v
254
254
  * @return {Number}
255
255
  */
256
- const clampZero = v => v < minValue ? minValue : v;
256
+ const normalizeTime = v => v <= minValue ? minValue : clampInfinity(round(v, 11));
257
257
  // Arrays
258
258
  /**
259
259
  * @template T
@@ -1112,14 +1112,34 @@ const morphTo = (path2, precision = .33) => ($path1) => {
1112
1112
  return [v1, v2];
1113
1113
  };
1114
1114
  /**
1115
- * @param {SVGGeometryElement} $el
1116
- * @param {Number} start
1117
- * @param {Number} end
1118
- * @return {Proxy}
1115
+ * @param {SVGGeometryElement} [$el]
1116
+ * @return {Number}
1119
1117
  */
1120
- function createDrawableProxy($el, start, end) {
1121
- const strokeLineCap = getComputedStyle($el).strokeLinecap;
1118
+ const getScaleFactor = $el => {
1119
+ let scaleFactor = 1;
1120
+ if ($el && $el.getCTM) {
1121
+ const ctm = $el.getCTM();
1122
+ if (ctm) {
1123
+ const scaleX = sqrt(ctm.a * ctm.a + ctm.b * ctm.b);
1124
+ const scaleY = sqrt(ctm.c * ctm.c + ctm.d * ctm.d);
1125
+ scaleFactor = (scaleX + scaleY) / 2;
1126
+ }
1127
+ }
1128
+ return scaleFactor;
1129
+ };
1130
+ /**
1131
+ * Creates a proxy that wraps an SVGGeometryElement and adds drawing functionality.
1132
+ * @param {SVGGeometryElement} $el - The SVG element to transform into a drawable
1133
+ * @param {number} start - Starting position (0-1)
1134
+ * @param {number} end - Ending position (0-1)
1135
+ * @return {DrawableSVGGeometry} - Returns a proxy that preserves the original element's type with additional 'draw' attribute functionality
1136
+ */
1137
+ const createDrawableProxy = ($el, start, end) => {
1122
1138
  const pathLength = K;
1139
+ const computedStyles = getComputedStyle($el);
1140
+ const strokeLineCap = computedStyles.strokeLinecap;
1141
+ // @ts-ignore
1142
+ const $scalled = computedStyles.vectorEffect === 'non-scaling-stroke' ? $el : null;
1123
1143
  let currentCap = strokeLineCap;
1124
1144
  const proxy = new Proxy($el, {
1125
1145
  get(target, property) {
@@ -1127,7 +1147,6 @@ function createDrawableProxy($el, start, end) {
1127
1147
  if (property === proxyTargetSymbol)
1128
1148
  return target;
1129
1149
  if (property === 'setAttribute') {
1130
- /** @param {any[]} args */
1131
1150
  return (...args) => {
1132
1151
  if (args[0] === 'draw') {
1133
1152
  const value = args[1];
@@ -1138,15 +1157,15 @@ function createDrawableProxy($el, start, end) {
1138
1157
  // const spaceIndex = value.indexOf(' ');
1139
1158
  // const v1 = round(+value.slice(0, spaceIndex), precision);
1140
1159
  // const v2 = round(+value.slice(spaceIndex + 1), precision);
1141
- const os = v1 * -1e3;
1142
- const d1 = (v2 * pathLength) + os;
1143
- // Prevents linecap to smear by offsetting the dasharray length by 0.01% when v2 is not at max
1144
- const d2 = (pathLength + ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10) - d1);
1145
- // Handle cases where the cap is still visible when the line is completly hidden
1160
+ const scaleFactor = getScaleFactor($scalled);
1161
+ const os = v1 * -1e3 * scaleFactor;
1162
+ const d1 = (v2 * pathLength * scaleFactor) + os;
1163
+ const d2 = (pathLength * scaleFactor +
1164
+ ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10 * scaleFactor) - d1);
1146
1165
  if (strokeLineCap !== 'butt') {
1147
1166
  const newCap = v1 === v2 ? 'butt' : strokeLineCap;
1148
1167
  if (currentCap !== newCap) {
1149
- target.setAttribute('stroke-linecap', `${newCap}`);
1168
+ target.style.strokeLinecap = `${newCap}`;
1150
1169
  currentCap = newCap;
1151
1170
  }
1152
1171
  }
@@ -1157,7 +1176,6 @@ function createDrawableProxy($el, start, end) {
1157
1176
  };
1158
1177
  }
1159
1178
  if (isFnc(value)) {
1160
- /** @param {any[]} args */
1161
1179
  return (...args) => Reflect.apply(value, target, args);
1162
1180
  }
1163
1181
  else {
@@ -1169,18 +1187,19 @@ function createDrawableProxy($el, start, end) {
1169
1187
  $el.setAttribute('pathLength', `${pathLength}`);
1170
1188
  proxy.setAttribute('draw', `${start} ${end}`);
1171
1189
  }
1172
- return /** @type {typeof Proxy} */ ( /** @type {unknown} */(proxy));
1173
- }
1190
+ return /** @type {DrawableSVGGeometry} */ (proxy);
1191
+ };
1174
1192
  /**
1175
- * @param {TargetsParam} selector
1176
- * @param {Number} [start=0]
1177
- * @param {Number} [end=0]
1178
- * @return {Array.<Proxy>}
1193
+ * Creates drawable proxies for multiple SVG elements.
1194
+ * @param {TargetsParam} selector - CSS selector, SVG element, or array of elements and selectors
1195
+ * @param {number} [start=0] - Starting position (0-1)
1196
+ * @param {number} [end=0] - Ending position (0-1)
1197
+ * @return {Array<DrawableSVGGeometry>} - Array of proxied elements with drawing functionality
1179
1198
  */
1180
1199
  const createDrawable = (selector, start = 0, end = 0) => {
1181
- const els = /** @type {Array.<Proxy>} */ (( /** @type {unknown} */(parseTargets(selector))));
1182
- els.forEach(($el, i) => els[i] = createDrawableProxy(/** @type {SVGGeometryElement} */ ( /** @type {unknown} */($el)), start, end));
1183
- return els;
1200
+ const els = parseTargets(selector);
1201
+ return els.map($el => createDrawableProxy(
1202
+ /** @type {SVGGeometryElement} */ ($el), start, end));
1184
1203
  };
1185
1204
  // Motion path animation
1186
1205
  /**
@@ -2093,12 +2112,13 @@ class Timer extends Clock {
2093
2112
  */
2094
2113
  stretch(newDuration) {
2095
2114
  const currentDuration = this.duration;
2096
- if (currentDuration === clampZero(newDuration))
2115
+ const normlizedDuration = normalizeTime(newDuration);
2116
+ if (currentDuration === normlizedDuration)
2097
2117
  return this;
2098
2118
  const timeScale = newDuration / currentDuration;
2099
2119
  const isSetter = newDuration <= minValue;
2100
- this.duration = isSetter ? minValue : clampZero(clampInfinity(round(currentDuration * timeScale, 12)));
2101
- this.iterationDuration = isSetter ? minValue : clampZero(clampInfinity(round(this.iterationDuration * timeScale, 12)));
2120
+ this.duration = isSetter ? minValue : normlizedDuration;
2121
+ this.iterationDuration = isSetter ? minValue : normalizeTime(this.iterationDuration * timeScale);
2102
2122
  this._offset *= timeScale;
2103
2123
  this._delay *= timeScale;
2104
2124
  this._loopDelay *= timeScale;
@@ -3051,14 +3071,14 @@ class JSAnimation extends Timer {
3051
3071
  */
3052
3072
  stretch(newDuration) {
3053
3073
  const currentDuration = this.duration;
3054
- if (currentDuration === clampZero(newDuration))
3074
+ if (currentDuration === normalizeTime(newDuration))
3055
3075
  return this;
3056
3076
  const timeScale = newDuration / currentDuration;
3057
3077
  // NOTE: Find a better way to handle the stretch of an animation after stretch = 0
3058
3078
  forEachChildren(this, (/** @type {Tween} */ tween) => {
3059
3079
  // Rounding is necessary here to minimize floating point errors
3060
- tween._updateDuration = clampZero(round(tween._updateDuration * timeScale, 12));
3061
- tween._changeDuration = clampZero(round(tween._changeDuration * timeScale, 12));
3080
+ tween._updateDuration = normalizeTime(tween._updateDuration * timeScale);
3081
+ tween._changeDuration = normalizeTime(tween._changeDuration * timeScale);
3062
3082
  tween._currentTime *= timeScale;
3063
3083
  tween._startTime *= timeScale;
3064
3084
  tween._absoluteStartTime *= timeScale;
@@ -3154,6 +3174,7 @@ const parseWAAPIEasing = (ease) => {
3154
3174
  if (isFnc(parsed))
3155
3175
  parsedEase = parsed === none ? 'linear' : easingToLinear(parsed);
3156
3176
  }
3177
+ WAAPIEasesLookups[ease] = parsedEase;
3157
3178
  }
3158
3179
  else if (isFnc(ease)) {
3159
3180
  const easing = easingToLinear(ease);
@@ -3163,7 +3184,7 @@ const parseWAAPIEasing = (ease) => {
3163
3184
  else if ( /** @type {Spring} */(ease).ease) {
3164
3185
  parsedEase = easingToLinear(/** @type {Spring} */ (ease).ease);
3165
3186
  }
3166
- return WAAPIEasesLookups[ease] = parsedEase;
3187
+ return parsedEase;
3167
3188
  };
3168
3189
  /**
3169
3190
  * @typedef {String|Number|Array<String>|Array<Number>} WAAPITweenValue
@@ -3226,6 +3247,8 @@ const validIndividualTransforms = [...transformsShorthands, ...validTransforms.f
3226
3247
  // Setting it to true in case CSS.registerProperty is not supported will automatically skip the registration and fallback to no animation
3227
3248
  let transformsPropertiesRegistered = isBrowser && (isUnd(CSS) || !Object.hasOwnProperty.call(CSS, 'registerProperty'));
3228
3249
  const registerTransformsProperties = () => {
3250
+ if (transformsPropertiesRegistered)
3251
+ return;
3229
3252
  validTransforms.forEach(t => {
3230
3253
  const isSkew = stringStartsWith(t, 'skew');
3231
3254
  const isScale = stringStartsWith(t, 'scale');
@@ -3233,12 +3256,15 @@ const registerTransformsProperties = () => {
3233
3256
  const isTranslate = stringStartsWith(t, 'translate');
3234
3257
  const isAngle = isRotate || isSkew;
3235
3258
  const syntax = isAngle ? '<angle>' : isScale ? "<number>" : isTranslate ? "<length-percentage>" : "*";
3236
- CSS.registerProperty({
3237
- name: '--' + t,
3238
- syntax,
3239
- inherits: false,
3240
- initialValue: isTranslate ? '0px' : isAngle ? '0deg' : isScale ? '1' : '0',
3241
- });
3259
+ try {
3260
+ CSS.registerProperty({
3261
+ name: '--' + t,
3262
+ syntax,
3263
+ inherits: false,
3264
+ initialValue: isTranslate ? '0px' : isAngle ? '0deg' : isScale ? '1' : '0',
3265
+ });
3266
+ }
3267
+ catch { }
3242
3268
  });
3243
3269
  transformsPropertiesRegistered = true;
3244
3270
  };
@@ -3356,8 +3382,7 @@ class WAAPIAnimation {
3356
3382
  constructor(targets, params) {
3357
3383
  if (globals.scope)
3358
3384
  globals.scope.revertibles.push(this);
3359
- if (!transformsPropertiesRegistered)
3360
- registerTransformsProperties();
3385
+ registerTransformsProperties();
3361
3386
  const parsedTargets = registerTargets(targets);
3362
3387
  const targetsLength = parsedTargets.length;
3363
3388
  if (!targetsLength) {
@@ -3513,7 +3538,14 @@ class WAAPIAnimation {
3513
3538
  /** @param {Number} time */
3514
3539
  set currentTime(time) {
3515
3540
  const t = time * (globals.timeScale === 1 ? 1 : K);
3516
- this.forEach(anim => anim.currentTime = t);
3541
+ this.forEach(anim => {
3542
+ // Make sure the animation playState is not 'paused' in order to properly trigger an onfinish callback.
3543
+ // 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.
3544
+ // https://developer.mozilla.org/en-US/docs/Web/API/Animation/finish_event
3545
+ if (t >= this.duration)
3546
+ anim.play();
3547
+ anim.currentTime = t;
3548
+ });
3517
3549
  }
3518
3550
  get progress() {
3519
3551
  return this.currentTime / this.duration;
@@ -4260,16 +4292,13 @@ class Timeline extends Timer {
4260
4292
  */
4261
4293
  stretch(newDuration) {
4262
4294
  const currentDuration = this.duration;
4263
- if (currentDuration === clampZero(newDuration))
4295
+ if (currentDuration === normalizeTime(newDuration))
4264
4296
  return this;
4265
4297
  const timeScale = newDuration / currentDuration;
4266
4298
  const labels = this.labels;
4267
- forEachChildren(this, (/** @type {JSAnimation} */ child) => {
4268
- child.stretch(child.duration * timeScale);
4269
- });
4270
- for (let labelName in labels) {
4299
+ forEachChildren(this, (/** @type {JSAnimation} */ child) => child.stretch(child.duration * timeScale));
4300
+ for (let labelName in labels)
4271
4301
  labels[labelName] *= timeScale;
4272
- }
4273
4302
  return super.stretch(newDuration);
4274
4303
  }
4275
4304
  /**
@@ -4620,11 +4649,6 @@ class Transforms {
4620
4649
  });
4621
4650
  }
4622
4651
  }
4623
- /**
4624
- * @typedef {Object} DraggableCursorParams
4625
- * @property {String} [onHover]
4626
- * @property {String} [onGrab]
4627
- */
4628
4652
  /**
4629
4653
  * @template {Array<Number>|DOMTargetSelector|String|Number|Boolean|Function|DraggableCursorParams} T
4630
4654
  * @param {T | ((draggable: Draggable) => T)} value
@@ -4633,45 +4657,6 @@ class Transforms {
4633
4657
  */
4634
4658
  const parseDraggableFunctionParameter = (value, draggable) => value && isFnc(value) ? /** @type {Function} */ (value)(draggable) : value;
4635
4659
  let zIndex = 0;
4636
- /**
4637
- * @typedef {Object} DraggableAxisParam
4638
- * @property {String} [mapTo]
4639
- * @property {TweenModifier} [modifier]
4640
- * @property {TweenComposition} [composition]
4641
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
4642
- */
4643
- /**
4644
- * @typedef {Object} DraggableParams
4645
- * @property {DOMTargetSelector} [trigger]
4646
- * @property {DOMTargetSelector|Array<Number>|((draggable: Draggable) => DOMTargetSelector|Array<Number>)} [container]
4647
- * @property {Boolean|DraggableAxisParam} [x]
4648
- * @property {Boolean|DraggableAxisParam} [y]
4649
- * @property {TweenModifier} [modifier]
4650
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [snap]
4651
- * @property {Number|Array<Number>|((draggable: Draggable) => Number|Array<Number>)} [containerPadding]
4652
- * @property {Number|((draggable: Draggable) => Number)} [containerFriction]
4653
- * @property {Number|((draggable: Draggable) => Number)} [releaseContainerFriction]
4654
- * @property {Number|((draggable: Draggable) => Number)} [dragSpeed]
4655
- * @property {Number|((draggable: Draggable) => Number)} [scrollSpeed]
4656
- * @property {Number|((draggable: Draggable) => Number)} [scrollThreshold]
4657
- * @property {Number|((draggable: Draggable) => Number)} [minVelocity]
4658
- * @property {Number|((draggable: Draggable) => Number)} [maxVelocity]
4659
- * @property {Number|((draggable: Draggable) => Number)} [velocityMultiplier]
4660
- * @property {Number} [releaseMass]
4661
- * @property {Number} [releaseStiffness]
4662
- * @property {Number} [releaseDamping]
4663
- * @property {Boolean} [releaseDamping]
4664
- * @property {EasingParam} [releaseEase]
4665
- * @property {Boolean|DraggableCursorParams|((draggable: Draggable) => Boolean|DraggableCursorParams)} [cursor]
4666
- * @property {Callback<Draggable>} [onGrab]
4667
- * @property {Callback<Draggable>} [onDrag]
4668
- * @property {Callback<Draggable>} [onRelease]
4669
- * @property {Callback<Draggable>} [onUpdate]
4670
- * @property {Callback<Draggable>} [onSettle]
4671
- * @property {Callback<Draggable>} [onSnap]
4672
- * @property {Callback<Draggable>} [onResize]
4673
- * @property {Callback<Draggable>} [onAfterResize]
4674
- */
4675
4660
  class Draggable {
4676
4661
  /**
4677
4662
  * @param {TargetsParam} target
@@ -4885,7 +4870,7 @@ class Draggable {
4885
4870
  this.canScroll = false;
4886
4871
  this.enabled = false;
4887
4872
  this.initialized = false;
4888
- this.activeProp = this.disabled[0] ? yProp : xProp;
4873
+ this.activeProp = this.disabled[1] ? xProp : yProp;
4889
4874
  this.animate.animations[this.activeProp].onRender = () => {
4890
4875
  const hasUpdated = this.updated;
4891
4876
  const hasMoved = this.grabbed && hasUpdated;
@@ -5665,6 +5650,7 @@ class Draggable {
5665
5650
  this.overshootXTicker.revert();
5666
5651
  this.overshootYTicker.revert();
5667
5652
  this.resizeTicker.revert();
5653
+ this.animate.revert();
5668
5654
  return this;
5669
5655
  }
5670
5656
  /**