animejs 4.3.6 → 4.4.1
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 +6 -9
- package/dist/bundles/anime.esm.js +973 -391
- package/dist/bundles/anime.esm.min.js +2 -2
- package/dist/bundles/anime.umd.js +977 -390
- package/dist/bundles/anime.umd.min.js +2 -2
- package/dist/modules/animatable/animatable.cjs +1 -1
- package/dist/modules/animatable/animatable.js +2 -2
- 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 +38 -16
- package/dist/modules/animation/animation.d.ts +2 -2
- package/dist/modules/animation/animation.js +42 -20
- package/dist/modules/animation/composition.cjs +1 -1
- package/dist/modules/animation/composition.js +3 -3
- package/dist/modules/animation/index.cjs +1 -1
- package/dist/modules/animation/index.js +1 -1
- package/dist/modules/core/clock.cjs +1 -1
- package/dist/modules/core/clock.js +1 -1
- package/dist/modules/core/colors.cjs +1 -1
- package/dist/modules/core/colors.js +1 -1
- package/dist/modules/core/consts.cjs +3 -9
- package/dist/modules/core/consts.d.ts +1 -5
- package/dist/modules/core/consts.js +4 -8
- package/dist/modules/core/globals.cjs +16 -5
- package/dist/modules/core/globals.d.ts +22 -1
- package/dist/modules/core/globals.js +18 -6
- package/dist/modules/core/helpers.cjs +7 -10
- package/dist/modules/core/helpers.js +8 -11
- package/dist/modules/core/render.cjs +7 -34
- package/dist/modules/core/render.js +8 -35
- package/dist/modules/core/styles.cjs +53 -32
- package/dist/modules/core/styles.d.ts +1 -0
- package/dist/modules/core/styles.js +55 -35
- package/dist/modules/core/targets.cjs +1 -1
- package/dist/modules/core/targets.js +1 -1
- package/dist/modules/core/transforms.cjs +129 -13
- package/dist/modules/core/transforms.d.ts +1 -0
- package/dist/modules/core/transforms.js +130 -15
- package/dist/modules/core/units.cjs +1 -1
- package/dist/modules/core/units.js +1 -1
- package/dist/modules/core/values.cjs +68 -8
- package/dist/modules/core/values.d.ts +5 -2
- package/dist/modules/core/values.js +69 -11
- 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 +1 -1
- package/dist/modules/easings/eases/parser.js +1 -1
- 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 +1 -1
- package/dist/modules/engine/engine.js +1 -1
- 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 +1 -1
- package/dist/modules/events/scroll.js +1 -1
- package/dist/modules/index.cjs +9 -1
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +4 -1
- package/dist/modules/layout/index.cjs +1 -1
- package/dist/modules/layout/index.js +1 -1
- package/dist/modules/layout/layout.cjs +29 -25
- package/dist/modules/layout/layout.d.ts +4 -3
- package/dist/modules/layout/layout.js +30 -26
- 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 +3 -6
- package/dist/modules/svg/morphto.js +3 -6
- package/dist/modules/svg/motionpath.cjs +1 -1
- package/dist/modules/svg/motionpath.js +1 -1
- package/dist/modules/text/index.cjs +3 -1
- package/dist/modules/text/index.d.ts +1 -0
- package/dist/modules/text/index.js +2 -1
- package/dist/modules/text/scramble.cjs +272 -0
- package/dist/modules/text/scramble.d.ts +3 -0
- package/dist/modules/text/scramble.js +270 -0
- package/dist/modules/text/split.cjs +5 -5
- package/dist/modules/text/split.d.ts +5 -5
- package/dist/modules/text/split.js +5 -5
- 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 +36 -18
- package/dist/modules/timeline/timeline.d.ts +6 -5
- package/dist/modules/timeline/timeline.js +37 -19
- package/dist/modules/timer/index.cjs +1 -1
- package/dist/modules/timer/index.js +1 -1
- package/dist/modules/timer/timer.cjs +8 -12
- package/dist/modules/timer/timer.d.ts +2 -0
- package/dist/modules/timer/timer.js +9 -13
- package/dist/modules/types/index.d.ts +76 -8
- package/dist/modules/utils/chainable.cjs +8 -5
- package/dist/modules/utils/chainable.js +8 -5
- package/dist/modules/utils/index.cjs +5 -1
- package/dist/modules/utils/index.d.ts +1 -0
- package/dist/modules/utils/index.js +2 -1
- package/dist/modules/utils/number.cjs +1 -1
- package/dist/modules/utils/number.js +1 -1
- package/dist/modules/utils/random.cjs +1 -1
- package/dist/modules/utils/random.js +1 -1
- package/dist/modules/utils/stagger.cjs +117 -20
- package/dist/modules/utils/stagger.js +118 -21
- package/dist/modules/utils/target.cjs +1 -1
- package/dist/modules/utils/target.js +1 -1
- package/dist/modules/utils/time.cjs +5 -3
- package/dist/modules/utils/time.d.ts +1 -1
- package/dist/modules/utils/time.js +5 -3
- 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 +19 -20
- package/dist/modules/waapi/waapi.js +20 -21
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anime.js - layout - ESM
|
|
3
|
-
* @version v4.
|
|
3
|
+
* @version v4.4.1
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 - Julian Garnier
|
|
6
6
|
*/
|
|
@@ -11,7 +11,7 @@ import { parseEase } from '../easings/eases/parser.js';
|
|
|
11
11
|
import { setValue, getFunctionValue } from '../core/values.js';
|
|
12
12
|
import { createTimeline } from '../timeline/timeline.js';
|
|
13
13
|
import { waapi } from '../waapi/waapi.js';
|
|
14
|
-
import { scope, defaults } from '../core/globals.js';
|
|
14
|
+
import { scope, defaults, globals } from '../core/globals.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @import {
|
|
@@ -77,6 +77,7 @@ import { scope, defaults } from '../core/globals.js';
|
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* @typedef {Object} LayoutSpecificAnimationParams
|
|
80
|
+
* @property {Number|String} [id]
|
|
80
81
|
* @property {Number|FunctionValue} [delay]
|
|
81
82
|
* @property {Number|FunctionValue} [duration]
|
|
82
83
|
* @property {EasingParam|FunctionValue} [ease]
|
|
@@ -119,7 +120,7 @@ import { scope, defaults } from '../core/globals.js';
|
|
|
119
120
|
* @property {String} id
|
|
120
121
|
* @property {DOMTarget} $el
|
|
121
122
|
* @property {Number} index
|
|
122
|
-
* @property {
|
|
123
|
+
* @property {Array<DOMTarget>} targets
|
|
123
124
|
* @property {Number} delay
|
|
124
125
|
* @property {Number} duration
|
|
125
126
|
* @property {EasingParam} ease
|
|
@@ -263,7 +264,7 @@ const createNode = ($el, parentNode, state, recycledNode) => {
|
|
|
263
264
|
node.$measure = $el;
|
|
264
265
|
node.id = dataId;
|
|
265
266
|
node.index = 0;
|
|
266
|
-
node.
|
|
267
|
+
node.targets = null;
|
|
267
268
|
node.delay = 0;
|
|
268
269
|
node.duration = 0;
|
|
269
270
|
node.ease = null;
|
|
@@ -449,12 +450,12 @@ const updateNodeProperties = (node, props) => {
|
|
|
449
450
|
* @param {LayoutAnimationTimingsParams} params
|
|
450
451
|
*/
|
|
451
452
|
const updateNodeTimingParams = (node, params) => {
|
|
452
|
-
const easeFunctionResult = getFunctionValue(params.ease, node.$el, node.index, node.
|
|
453
|
+
const easeFunctionResult = getFunctionValue(params.ease, node.$el, node.index, node.targets, null, null);
|
|
453
454
|
const keyEasing = isFnc(easeFunctionResult) ? easeFunctionResult : params.ease;
|
|
454
455
|
const hasSpring = !isUnd(keyEasing) && !isUnd(/** @type {Spring} */(keyEasing).ease);
|
|
455
456
|
node.ease = hasSpring ? /** @type {Spring} */(keyEasing).ease : keyEasing;
|
|
456
|
-
node.duration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(params.duration, node.$el, node.index, node.
|
|
457
|
-
node.delay = getFunctionValue(params.delay, node.$el, node.index, node.
|
|
457
|
+
node.duration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(params.duration, node.$el, node.index, node.targets, null, null);
|
|
458
|
+
node.delay = getFunctionValue(params.delay, node.$el, node.index, node.targets, null, null);
|
|
458
459
|
};
|
|
459
460
|
|
|
460
461
|
/**
|
|
@@ -827,10 +828,12 @@ class LayoutSnapshot {
|
|
|
827
828
|
|
|
828
829
|
const inRootNodeIds = new Set();
|
|
829
830
|
// Update index and total for inital timing calculation
|
|
830
|
-
let index = 0
|
|
831
|
+
let index = 0;
|
|
832
|
+
const allNodeTargets = [];
|
|
833
|
+
this.nodes.forEach((node) => { allNodeTargets.push(node.$el); });
|
|
831
834
|
this.nodes.forEach((node, id) => {
|
|
832
835
|
node.index = index++;
|
|
833
|
-
node.
|
|
836
|
+
node.targets = allNodeTargets;
|
|
834
837
|
// Track ids of nodes that belong to the current root to filter detached matches
|
|
835
838
|
if (node && node.measuredIsInsideRoot) {
|
|
836
839
|
inRootNodeIds.add(id);
|
|
@@ -942,8 +945,8 @@ class AutoLayout {
|
|
|
942
945
|
this.params = params;
|
|
943
946
|
/** @type {DOMTarget} */
|
|
944
947
|
this.root = /** @type {DOMTarget} */(registerTargets(root)[0]);
|
|
945
|
-
/** @type {Number} */
|
|
946
|
-
this.id = layoutId++;
|
|
948
|
+
/** @type {Number|String} */
|
|
949
|
+
this.id = params.id || layoutId++;
|
|
947
950
|
/** @type {LayoutChildrenParam} */
|
|
948
951
|
this.children = params.children || '*';
|
|
949
952
|
/** @type {Boolean} */
|
|
@@ -1066,7 +1069,9 @@ class AutoLayout {
|
|
|
1066
1069
|
duration: setValue(params.duration, this.params.duration),
|
|
1067
1070
|
};
|
|
1068
1071
|
/** @type {TimelineParams} */
|
|
1069
|
-
const tlParams = {
|
|
1072
|
+
const tlParams = {
|
|
1073
|
+
id: this.id
|
|
1074
|
+
};
|
|
1070
1075
|
const onComplete = setValue(params.onComplete, this.params.onComplete);
|
|
1071
1076
|
const onPause = setValue(params.onPause, this.params.onPause);
|
|
1072
1077
|
for (let name in defaults) {
|
|
@@ -1080,7 +1085,8 @@ class AutoLayout {
|
|
|
1080
1085
|
}
|
|
1081
1086
|
tlParams.onComplete = () => {
|
|
1082
1087
|
const ap = /** @type {ScrollObserver} */(params.autoplay);
|
|
1083
|
-
const
|
|
1088
|
+
const ed = globals.editor;
|
|
1089
|
+
const isScrollControled = (ap && ap.linked) || (ed && ed.showPanel);
|
|
1084
1090
|
if (isScrollControled) {
|
|
1085
1091
|
if (onComplete) onComplete(this.timeline);
|
|
1086
1092
|
return;
|
|
@@ -1279,41 +1285,39 @@ class AutoLayout {
|
|
|
1279
1285
|
animatedParent = animatedParent.parentNode;
|
|
1280
1286
|
}
|
|
1281
1287
|
|
|
1282
|
-
const animatingTotal = animating.length;
|
|
1283
|
-
|
|
1284
1288
|
// Root is always animated first in sync with the first child (animating.length is the total of children)
|
|
1285
1289
|
if (node === rootNode) {
|
|
1286
1290
|
node.index = 0;
|
|
1287
|
-
node.
|
|
1291
|
+
node.targets = animating;
|
|
1288
1292
|
updateNodeTimingParams(node, animationTimings);
|
|
1289
1293
|
} else if (node.isEntering) {
|
|
1290
1294
|
node.index = animatedParent ? animatedParent.index : enteringIndex;
|
|
1291
|
-
node.
|
|
1295
|
+
node.targets = animatedParent ? animating : entering;
|
|
1292
1296
|
updateNodeTimingParams(node, enterFromTimings);
|
|
1293
1297
|
enteringIndex++;
|
|
1294
1298
|
} else if (node.isLeaving) {
|
|
1295
1299
|
node.index = animatedParent ? animatedParent.index : leavingIndex;
|
|
1296
|
-
node.
|
|
1300
|
+
node.targets = animatedParent ? animating : leaving;
|
|
1297
1301
|
leavingIndex++;
|
|
1298
1302
|
updateNodeTimingParams(node, leaveToTimings);
|
|
1299
1303
|
} else if (node.isTarget) {
|
|
1300
1304
|
node.index = animatingIndex++;
|
|
1301
|
-
node.
|
|
1305
|
+
node.targets = animating;
|
|
1302
1306
|
updateNodeTimingParams(node, animationTimings);
|
|
1303
1307
|
} else {
|
|
1304
1308
|
node.index = animatedParent ? animatedParent.index : 0;
|
|
1305
|
-
node.
|
|
1309
|
+
node.targets = animating;
|
|
1306
1310
|
updateNodeTimingParams(node, swapAtTimings);
|
|
1307
1311
|
}
|
|
1308
1312
|
|
|
1309
1313
|
// Make sure the old state node has its inex and total values up to date for valid "from" function values calculation
|
|
1310
1314
|
oldStateNode.index = node.index;
|
|
1311
|
-
oldStateNode.
|
|
1315
|
+
oldStateNode.targets = node.targets;
|
|
1312
1316
|
|
|
1313
1317
|
// Computes all values up front so we can check for changes and we don't have to re-compute them inside the animation props
|
|
1314
1318
|
for (let prop in nodeProperties) {
|
|
1315
|
-
nodeProperties[prop] = getFunctionValue(nodeProperties[prop], $el, node.index, node.
|
|
1316
|
-
oldStateNodeProperties[prop] = getFunctionValue(oldStateNodeProperties[prop], $el, oldStateNode.index, oldStateNode.
|
|
1319
|
+
nodeProperties[prop] = getFunctionValue(nodeProperties[prop], $el, node.index, node.targets, null, null);
|
|
1320
|
+
oldStateNodeProperties[prop] = getFunctionValue(oldStateNodeProperties[prop], $el, oldStateNode.index, oldStateNode.targets, null, null);
|
|
1317
1321
|
}
|
|
1318
1322
|
|
|
1319
1323
|
// Use a 1px tolerance to detect dimensions changes to prevent width / height animations on barelly visible elements
|
|
@@ -1539,8 +1543,8 @@ class AutoLayout {
|
|
|
1539
1543
|
}
|
|
1540
1544
|
$el.style.transform = oldState.getComputedValue($el, 'transform');
|
|
1541
1545
|
if (animatedSwap.includes($el)) {
|
|
1542
|
-
node.ease = getFunctionValue(swapAtParams.ease, $el, node.index, node.
|
|
1543
|
-
node.duration = getFunctionValue(swapAtParams.duration, $el, node.index, node.
|
|
1546
|
+
node.ease = getFunctionValue(swapAtParams.ease, $el, node.index, node.targets, null, null);
|
|
1547
|
+
node.duration = getFunctionValue(swapAtParams.duration, $el, node.index, node.targets, null, null);
|
|
1544
1548
|
}
|
|
1545
1549
|
}
|
|
1546
1550
|
this.transformAnimation = waapi.animate(transformed, {
|
|
@@ -1555,7 +1559,7 @@ class AutoLayout {
|
|
|
1555
1559
|
if (!animatedSwap.includes($el)) return newValue;
|
|
1556
1560
|
const oldValue = oldState.getComputedValue($el, 'transform');
|
|
1557
1561
|
const node = newState.getNode($el);
|
|
1558
|
-
return [oldValue, getFunctionValue(swapAtProps.transform, $el, node.index, node.
|
|
1562
|
+
return [oldValue, getFunctionValue(swapAtProps.transform, $el, node.index, node.targets, null, null), newValue]
|
|
1559
1563
|
},
|
|
1560
1564
|
autoplay: false,
|
|
1561
1565
|
// persist: true,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anime.js - svg - CJS
|
|
3
|
-
* @version v4.
|
|
3
|
+
* @version v4.4.1
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 - Julian Garnier
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
var consts = require('../core/consts.cjs');
|
|
11
10
|
var helpers$1 = require('../core/helpers.cjs');
|
|
12
11
|
var helpers = require('./helpers.cjs');
|
|
13
12
|
|
|
@@ -23,7 +22,7 @@ var helpers = require('./helpers.cjs');
|
|
|
23
22
|
* @param {Number} [precision]
|
|
24
23
|
* @return {FunctionValue}
|
|
25
24
|
*/
|
|
26
|
-
const morphTo = (path2, precision = .33) => ($path1) => {
|
|
25
|
+
const morphTo = (path2, precision = .33) => ($path1, index, total, prevTween) => {
|
|
27
26
|
const tagName1 = ($path1.tagName || '').toLowerCase();
|
|
28
27
|
if (!tagName1.match(/^(path|polygon|polyline)$/)) {
|
|
29
28
|
throw new Error(`Can't morph a <${$path1.tagName}> SVG element. Use <path>, <polygon> or <polyline>.`);
|
|
@@ -38,7 +37,7 @@ const morphTo = (path2, precision = .33) => ($path1) => {
|
|
|
38
37
|
}
|
|
39
38
|
const isPath = $path1.tagName === 'path';
|
|
40
39
|
const separator = isPath ? ' ' : ',';
|
|
41
|
-
const previousPoints =
|
|
40
|
+
const previousPoints = prevTween ? prevTween._value : null;
|
|
42
41
|
if (previousPoints) $path1.setAttribute(isPath ? 'd' : 'points', previousPoints);
|
|
43
42
|
|
|
44
43
|
let v1 = '', v2 = '';
|
|
@@ -60,8 +59,6 @@ const morphTo = (path2, precision = .33) => ($path1) => {
|
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
$path1[consts.morphPointsSymbol] = v2;
|
|
64
|
-
|
|
65
62
|
return [v1, v2];
|
|
66
63
|
};
|
|
67
64
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anime.js - svg - ESM
|
|
3
|
-
* @version v4.
|
|
3
|
+
* @version v4.4.1
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 - Julian Garnier
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { morphPointsSymbol } from '../core/consts.js';
|
|
9
8
|
import { round } from '../core/helpers.js';
|
|
10
9
|
import { getPath } from './helpers.js';
|
|
11
10
|
|
|
@@ -21,7 +20,7 @@ import { getPath } from './helpers.js';
|
|
|
21
20
|
* @param {Number} [precision]
|
|
22
21
|
* @return {FunctionValue}
|
|
23
22
|
*/
|
|
24
|
-
const morphTo = (path2, precision = .33) => ($path1) => {
|
|
23
|
+
const morphTo = (path2, precision = .33) => ($path1, index, total, prevTween) => {
|
|
25
24
|
const tagName1 = ($path1.tagName || '').toLowerCase();
|
|
26
25
|
if (!tagName1.match(/^(path|polygon|polyline)$/)) {
|
|
27
26
|
throw new Error(`Can't morph a <${$path1.tagName}> SVG element. Use <path>, <polygon> or <polyline>.`);
|
|
@@ -36,7 +35,7 @@ const morphTo = (path2, precision = .33) => ($path1) => {
|
|
|
36
35
|
}
|
|
37
36
|
const isPath = $path1.tagName === 'path';
|
|
38
37
|
const separator = isPath ? ' ' : ',';
|
|
39
|
-
const previousPoints =
|
|
38
|
+
const previousPoints = prevTween ? prevTween._value : null;
|
|
40
39
|
if (previousPoints) $path1.setAttribute(isPath ? 'd' : 'points', previousPoints);
|
|
41
40
|
|
|
42
41
|
let v1 = '', v2 = '';
|
|
@@ -58,8 +57,6 @@ const morphTo = (path2, precision = .33) => ($path1) => {
|
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
$path1[morphPointsSymbol] = v2;
|
|
62
|
-
|
|
63
60
|
return [v1, v2];
|
|
64
61
|
};
|
|
65
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anime.js - text - CJS
|
|
3
|
-
* @version v4.
|
|
3
|
+
* @version v4.4.1
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 - Julian Garnier
|
|
6
6
|
*/
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
10
|
var split = require('./split.cjs');
|
|
11
|
+
var scramble = require('./scramble.cjs');
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
exports.TextSplitter = split.TextSplitter;
|
|
15
16
|
exports.split = split.split;
|
|
16
17
|
exports.splitText = split.splitText;
|
|
18
|
+
exports.scrambleText = scramble.scrambleText;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anime.js - text - CJS
|
|
3
|
+
* @version v4.4.1
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright 2026 - Julian Garnier
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
var random = require('../utils/random.cjs');
|
|
11
|
+
var globals = require('../core/globals.cjs');
|
|
12
|
+
var helpers = require('../core/helpers.cjs');
|
|
13
|
+
var parser = require('../easings/eases/parser.cjs');
|
|
14
|
+
var consts = require('../core/consts.cjs');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @import {
|
|
18
|
+
* ScrambleTextParams,
|
|
19
|
+
* FunctionValue,
|
|
20
|
+
* } from '../types/index.js'
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* '-' 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-')
|
|
25
|
+
* @param {String} str
|
|
26
|
+
* @return {String}
|
|
27
|
+
*/
|
|
28
|
+
const expandCharRanges = (str) => {
|
|
29
|
+
let result = '';
|
|
30
|
+
for (let i = 0, l = str.length; i < l; i++) {
|
|
31
|
+
if (i + 2 < l && str[i + 1] === '-' && str.charCodeAt(i) < str.charCodeAt(i + 2)) {
|
|
32
|
+
const start = str.charCodeAt(i);
|
|
33
|
+
const end = str.charCodeAt(i + 2);
|
|
34
|
+
for (let c = start; c <= end; c++) result += String.fromCharCode(c);
|
|
35
|
+
i += 2;
|
|
36
|
+
} else {
|
|
37
|
+
result += str[i];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const charSets = {
|
|
44
|
+
lowercase: 'a-z',
|
|
45
|
+
uppercase: 'A-Z',
|
|
46
|
+
numbers: '0-9',
|
|
47
|
+
symbols: '!%#_|*+=',
|
|
48
|
+
braille: '⠀-⣿',
|
|
49
|
+
blocks: '▀-▟',
|
|
50
|
+
shades: '░-▓',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const originalTexts = new WeakMap();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns a function-based tween value that scrambles the target's text content,
|
|
57
|
+
* progressively revealing the original text.
|
|
58
|
+
*
|
|
59
|
+
* @param {ScrambleTextParams} [params]
|
|
60
|
+
* @return {FunctionValue}
|
|
61
|
+
*/
|
|
62
|
+
const scrambleText = (params = {}) => {
|
|
63
|
+
if (!params) params = {};
|
|
64
|
+
const charsParam = params.chars;
|
|
65
|
+
const easeFn = parser.parseEase(params.ease || 'linear');
|
|
66
|
+
const text = params.text;
|
|
67
|
+
const fromParam = params.from;
|
|
68
|
+
const reversed = params.reversed || false;
|
|
69
|
+
const perturbation = params.perturbation || 0;
|
|
70
|
+
const cursorParam = params.cursor;
|
|
71
|
+
const cursorChars = cursorParam === true ? '_'
|
|
72
|
+
: typeof cursorParam === 'number' ? String.fromCharCode(cursorParam)
|
|
73
|
+
: typeof cursorParam === 'string' ? cursorParam
|
|
74
|
+
: '';
|
|
75
|
+
const cursorLen = cursorChars.length;
|
|
76
|
+
const seed = params.seed || 0;
|
|
77
|
+
const override = params.override !== undefined ? params.override : true;
|
|
78
|
+
const revealRate = params.revealRate || 60;
|
|
79
|
+
const interval = 1000 * globals.globals.timeScale / revealRate;
|
|
80
|
+
const settleDuration = params.settleDuration || 300 * globals.globals.timeScale;
|
|
81
|
+
const settleRate = params.settleRate || 30;
|
|
82
|
+
const durationParam = params.duration;
|
|
83
|
+
const revealDelayParam = params.revealDelay;
|
|
84
|
+
const delayParam = params.delay;
|
|
85
|
+
const onChange = params.onChange || consts.noop;
|
|
86
|
+
|
|
87
|
+
return (target, index, targets, prevTween) => {
|
|
88
|
+
const rawChars = typeof charsParam === 'function' ? charsParam(target, index, targets) : (charsParam || 'a-zA-Z0-9!%#_');
|
|
89
|
+
const characters = expandCharRanges(charSets[rawChars] || rawChars);
|
|
90
|
+
const totalChars = characters.length - 1;
|
|
91
|
+
const duration = typeof durationParam === 'function' ? durationParam(target, index, targets) : durationParam;
|
|
92
|
+
const revealDelay = typeof revealDelayParam === 'function' ? revealDelayParam(target, index, targets) : (revealDelayParam || 0);
|
|
93
|
+
const delay = typeof delayParam === 'function' ? delayParam(target, index, targets) : (delayParam || 0);
|
|
94
|
+
const rng = seed ? random.createSeededRandom(seed) : random.createSeededRandom();
|
|
95
|
+
if (!originalTexts.has(target)) originalTexts.set(target, target.textContent);
|
|
96
|
+
const startingText = prevTween ? prevTween._value : target.textContent;
|
|
97
|
+
const targetText = text !== undefined
|
|
98
|
+
? (typeof text === 'function' ? text(target, index, targets) : text)
|
|
99
|
+
: prevTween ? prevTween._value
|
|
100
|
+
: originalTexts.get(target);
|
|
101
|
+
const settledText = targetText === ' ' || targetText === ' ' ? ' ' : targetText;
|
|
102
|
+
const startLength = startingText === ' ' ? 0 : startingText.length;
|
|
103
|
+
const endLength = settledText.length;
|
|
104
|
+
const overrideChars = override === true ? characters
|
|
105
|
+
: typeof override === 'string' && override.length > 0 ? expandCharRanges(charSets[/** @type {String} */(override)] || /** @type {String} */(override))
|
|
106
|
+
: null;
|
|
107
|
+
const totalOverrideChars = overrideChars ? overrideChars.length - 1 : 0;
|
|
108
|
+
// Space override uses so the browser doesn't collapse consecutive spaces in innerHTML
|
|
109
|
+
const overrideChar = override === ' ' ? ' ' : null;
|
|
110
|
+
// When starting from blank, only animate the target text length to avoid padding beyond it
|
|
111
|
+
const animLength = override === '' ? endLength : Math.max(startLength, endLength);
|
|
112
|
+
// Compute total duration from interval spacing and settle time, or use the explicit duration
|
|
113
|
+
const animDuration = duration > 0 ? duration : (animLength - 1) * interval + settleDuration;
|
|
114
|
+
const computedDuration = helpers.round((animDuration + revealDelay) / globals.globals.timeScale, 0) * globals.globals.timeScale;
|
|
115
|
+
const revealDelayRatio = revealDelay > 0 ? helpers.round(revealDelay / computedDuration, 12) : 0;
|
|
116
|
+
// Auto-resolve reveal direction: shrinking text reveals from right, growing from left
|
|
117
|
+
const resolvedFrom = fromParam === undefined || fromParam === 'auto' ? (endLength < startLength ? 'right' : 'left') : fromParam;
|
|
118
|
+
const charOrder = new Int32Array(animLength);
|
|
119
|
+
if (resolvedFrom === 'random') {
|
|
120
|
+
for (let i = 0; i < animLength; i++) charOrder[i] = i;
|
|
121
|
+
for (let i = animLength - 1; i > 0; i--) {
|
|
122
|
+
const j = rng(0, i);
|
|
123
|
+
const t = charOrder[i]; charOrder[i] = charOrder[j]; charOrder[j] = t;
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
const ref = resolvedFrom === 'right' ? (override === '' || !startLength ? animLength : startLength) - 1
|
|
127
|
+
: resolvedFrom === 'center' ? ((override === '' || !startLength ? animLength : startLength) - 1) / 2
|
|
128
|
+
: typeof resolvedFrom === 'number' ? resolvedFrom
|
|
129
|
+
: 0;
|
|
130
|
+
const abs = Math.abs;
|
|
131
|
+
const indices = new Array(animLength);
|
|
132
|
+
for (let i = 0; i < animLength; i++) indices[i] = i;
|
|
133
|
+
indices.sort((a, b) => abs(a - ref) - abs(b - ref));
|
|
134
|
+
for (let i = 0; i < animLength; i++) charOrder[indices[i]] = i;
|
|
135
|
+
}
|
|
136
|
+
if (reversed) {
|
|
137
|
+
const last = animLength - 1;
|
|
138
|
+
for (let i = 0; i < animLength; i++) charOrder[i] = last - charOrder[i];
|
|
139
|
+
}
|
|
140
|
+
// settleRatio is the fraction of the animation each character spends in the active scrambling zone
|
|
141
|
+
const settleRatio = helpers.round(settleDuration / animDuration, 12);
|
|
142
|
+
// settleSpacing is the time gap between consecutive characters entering the active zone
|
|
143
|
+
const settleSpacing = helpers.round((1 - settleRatio) / animLength, 12);
|
|
144
|
+
const cursorZone = cursorLen * settleSpacing;
|
|
145
|
+
// stepRatio controls how often scramble characters refresh (based on settleRate)
|
|
146
|
+
const stepRatio = helpers.round(1000 * globals.globals.timeScale / (settleRate * computedDuration), 12);
|
|
147
|
+
// Pre-compute per-character start and settle times
|
|
148
|
+
const charStarts = new Float32Array(animLength);
|
|
149
|
+
const charEnds = new Float32Array(animLength);
|
|
150
|
+
const scale = perturbation > 0 ? perturbation * settleRatio : 0;
|
|
151
|
+
for (let c = 0; c < animLength; c++) {
|
|
152
|
+
const so = scale > 0 ? (rng(0, 2000) - 1000) / 1000 * scale : 0;
|
|
153
|
+
const eo = scale > 0 ? (rng(0, 2000) - 1000) / 1000 * scale : 0;
|
|
154
|
+
charStarts[c] = charOrder[c] * settleSpacing + so;
|
|
155
|
+
charEnds[c] = Math.ceil((charStarts[c] + settleRatio + eo) / stepRatio) * stepRatio;
|
|
156
|
+
}
|
|
157
|
+
// When text shrinks with non-sequential from modes, delay target settle times past all extras
|
|
158
|
+
if (endLength < animLength && resolvedFrom !== 'left' && resolvedFrom !== 'right' && resolvedFrom !== 'random') {
|
|
159
|
+
let maxExtraEnd = 0;
|
|
160
|
+
for (let c = endLength; c < animLength; c++) {
|
|
161
|
+
if (charEnds[c] > maxExtraEnd) maxExtraEnd = charEnds[c];
|
|
162
|
+
}
|
|
163
|
+
const targets = new Array(endLength);
|
|
164
|
+
for (let c = 0; c < endLength; c++) targets[c] = c;
|
|
165
|
+
targets.sort((a, b) => charOrder[a] - charOrder[b]);
|
|
166
|
+
const targetSpacing = (1 - maxExtraEnd) / endLength;
|
|
167
|
+
for (let i = 0; i < endLength; i++) {
|
|
168
|
+
const revealTime = maxExtraEnd + i * targetSpacing;
|
|
169
|
+
if (revealTime > charEnds[targets[i]]) {
|
|
170
|
+
charEnds[targets[i]] = revealTime;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// charCache holds the current scramble character for each position, refreshed at settleRate
|
|
175
|
+
const charCache = new Array(animLength);
|
|
176
|
+
for (let c = 0; c < animLength; c++) {
|
|
177
|
+
charCache[c] = characters[rng(0, totalChars)];
|
|
178
|
+
}
|
|
179
|
+
// overrideCache holds scramble characters for the starting text (override: true or custom string)
|
|
180
|
+
const overrideCache = overrideChars ? (overrideChars === characters ? charCache : new Array(animLength)) : null;
|
|
181
|
+
if (overrideCache && overrideCache !== charCache) {
|
|
182
|
+
for (let c = 0; c < animLength; c++) {
|
|
183
|
+
overrideCache[c] = overrideChar || /** @type {String} */(overrideChars)[rng(0, overrideChars.length - 1)];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Build the initial display text based on override mode
|
|
187
|
+
let fillStartText = startingText;
|
|
188
|
+
if (!prevTween) {
|
|
189
|
+
if (override === '') {
|
|
190
|
+
fillStartText = '';
|
|
191
|
+
} else if (overrideChars) {
|
|
192
|
+
fillStartText = '';
|
|
193
|
+
for (let c = 0; c < startLength; c++) {
|
|
194
|
+
fillStartText += startingText[c] === ' ' ? ' ' : /** @type {Array<String>} */(overrideCache)[c];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let lastValue = -1;
|
|
200
|
+
let lastStep = -1;
|
|
201
|
+
let scrambled = '';
|
|
202
|
+
const hasOverride = override !== '';
|
|
203
|
+
const hasOverrideChars = !!overrideChars;
|
|
204
|
+
const hasCursor = cursorLen > 0;
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
from: 0,
|
|
208
|
+
to: 1,
|
|
209
|
+
duration: computedDuration,
|
|
210
|
+
delay: delay,
|
|
211
|
+
ease: 'linear',
|
|
212
|
+
modifier: (v) => {
|
|
213
|
+
if (v === lastValue) return scrambled;
|
|
214
|
+
lastValue = v;
|
|
215
|
+
if (delay > 0 && v <= 0) { scrambled = startingText; return startingText; }
|
|
216
|
+
if (v <= 0) { scrambled = fillStartText; return fillStartText; }
|
|
217
|
+
if (v >= 1) { scrambled = settledText; return settledText; }
|
|
218
|
+
scrambled = '';
|
|
219
|
+
// Only refresh scramble characters when we cross a settleRate step boundary
|
|
220
|
+
const currentStep = (v / stepRatio) | 0;
|
|
221
|
+
const refreshChars = currentStep !== lastStep;
|
|
222
|
+
if (refreshChars) lastStep = currentStep;
|
|
223
|
+
// Subtract delay ratio to get the effective animation progress
|
|
224
|
+
const linear = revealDelayRatio > 0 ? (v - revealDelayRatio) / (1 - revealDelayRatio) : v;
|
|
225
|
+
const t = linear > 0 ? easeFn(linear) : 0;
|
|
226
|
+
for (let c = 0; c < animLength; c++) {
|
|
227
|
+
// Each character has its own start/end window based on its reveal order
|
|
228
|
+
const charStart = charStarts[c];
|
|
229
|
+
const charEnd = charEnds[c];
|
|
230
|
+
// Settled zone: character has finished its transition
|
|
231
|
+
if (t >= charEnd) {
|
|
232
|
+
if (c < endLength) scrambled += settledText[c];
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
// Pre-transition zone: reveal wave hasn't reached this character yet
|
|
236
|
+
if (t <= 0 || t < charStart) {
|
|
237
|
+
if (hasOverride && c < startLength) {
|
|
238
|
+
if (hasOverrideChars) {
|
|
239
|
+
if (startingText[c] === ' ') {
|
|
240
|
+
scrambled += ' ';
|
|
241
|
+
} else {
|
|
242
|
+
if (refreshChars) /** @type {Array<String>} */(overrideCache)[c] = overrideChar || /** @type {String} */(overrideChars)[rng(0, totalOverrideChars)];
|
|
243
|
+
scrambled += /** @type {Array<String>} */(overrideCache)[c];
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
// Default (override: false): show the original starting text
|
|
247
|
+
scrambled += startingText[c];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
// Active zone: character is between charStart and charEnd
|
|
253
|
+
const isSpace = (c < endLength && settledText[c] === ' ') || (c < startLength && startingText[c] === ' ');
|
|
254
|
+
if (isSpace) {
|
|
255
|
+
scrambled += ' ';
|
|
256
|
+
} else if (hasCursor && t - charStart < cursorZone) {
|
|
257
|
+
// Cursor sub-zone: show cursor character based on position within cursor width
|
|
258
|
+
scrambled += cursorChars[cursorLen - 1 - (((t - charStart) / settleSpacing) | 0)];
|
|
259
|
+
} else {
|
|
260
|
+
// Scramble zone: show cycling random characters
|
|
261
|
+
if (refreshChars) charCache[c] = characters[rng(0, totalChars)];
|
|
262
|
+
scrambled += charCache[c];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (refreshChars) onChange(scrambled, t);
|
|
266
|
+
return scrambled;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
exports.scrambleText = scrambleText;
|