anime-rails 3.2.1.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.
@@ -0,0 +1,1289 @@
1
+ // Defaults
2
+
3
+ const defaultInstanceSettings = {
4
+ update: null,
5
+ begin: null,
6
+ loopBegin: null,
7
+ changeBegin: null,
8
+ change: null,
9
+ changeComplete: null,
10
+ loopComplete: null,
11
+ complete: null,
12
+ loop: 1,
13
+ direction: 'normal',
14
+ autoplay: true,
15
+ timelineOffset: 0
16
+ }
17
+
18
+ const defaultTweenSettings = {
19
+ duration: 1000,
20
+ delay: 0,
21
+ endDelay: 0,
22
+ easing: 'easeOutElastic(1, .5)',
23
+ round: 0
24
+ }
25
+
26
+ const validTransforms = ['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'perspective', 'matrix', 'matrix3d'];
27
+
28
+ // Caching
29
+
30
+ const cache = {
31
+ CSS: {},
32
+ springs: {}
33
+ }
34
+
35
+ // Utils
36
+
37
+ function minMax(val, min, max) {
38
+ return Math.min(Math.max(val, min), max);
39
+ }
40
+
41
+ function stringContains(str, text) {
42
+ return str.indexOf(text) > -1;
43
+ }
44
+
45
+ function applyArguments(func, args) {
46
+ return func.apply(null, args);
47
+ }
48
+
49
+ const is = {
50
+ arr: a => Array.isArray(a),
51
+ obj: a => stringContains(Object.prototype.toString.call(a), 'Object'),
52
+ pth: a => is.obj(a) && a.hasOwnProperty('totalLength'),
53
+ svg: a => a instanceof SVGElement,
54
+ inp: a => a instanceof HTMLInputElement,
55
+ dom: a => a.nodeType || is.svg(a),
56
+ str: a => typeof a === 'string',
57
+ fnc: a => typeof a === 'function',
58
+ und: a => typeof a === 'undefined',
59
+ nil: a => is.und(a) || a === null,
60
+ hex: a => /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a),
61
+ rgb: a => /^rgb/.test(a),
62
+ hsl: a => /^hsl/.test(a),
63
+ col: a => (is.hex(a) || is.rgb(a) || is.hsl(a)),
64
+ key: a => !defaultInstanceSettings.hasOwnProperty(a) && !defaultTweenSettings.hasOwnProperty(a) && a !== 'targets' && a !== 'keyframes',
65
+ }
66
+
67
+ // Easings
68
+
69
+ function parseEasingParameters(string) {
70
+ const match = /\(([^)]+)\)/.exec(string);
71
+ return match ? match[1].split(',').map(p => parseFloat(p)) : [];
72
+ }
73
+
74
+ // Spring solver inspired by Webkit Copyright © 2016 Apple Inc. All rights reserved. https://webkit.org/demos/spring/spring.js
75
+
76
+ function spring(string, duration) {
77
+
78
+ const params = parseEasingParameters(string);
79
+ const mass = minMax(is.und(params[0]) ? 1 : params[0], .1, 100);
80
+ const stiffness = minMax(is.und(params[1]) ? 100 : params[1], .1, 100);
81
+ const damping = minMax(is.und(params[2]) ? 10 : params[2], .1, 100);
82
+ const velocity = minMax(is.und(params[3]) ? 0 : params[3], .1, 100);
83
+ const w0 = Math.sqrt(stiffness / mass);
84
+ const zeta = damping / (2 * Math.sqrt(stiffness * mass));
85
+ const wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0;
86
+ const a = 1;
87
+ const b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0;
88
+
89
+ function solver(t) {
90
+ let progress = duration ? (duration * t) / 1000 : t;
91
+ if (zeta < 1) {
92
+ progress = Math.exp(-progress * zeta * w0) * (a * Math.cos(wd * progress) + b * Math.sin(wd * progress));
93
+ } else {
94
+ progress = (a + b * progress) * Math.exp(-progress * w0);
95
+ }
96
+ if (t === 0 || t === 1) return t;
97
+ return 1 - progress;
98
+ }
99
+
100
+ function getDuration() {
101
+ const cached = cache.springs[string];
102
+ if (cached) return cached;
103
+ const frame = 1/6;
104
+ let elapsed = 0;
105
+ let rest = 0;
106
+ while(true) {
107
+ elapsed += frame;
108
+ if (solver(elapsed) === 1) {
109
+ rest++;
110
+ if (rest >= 16) break;
111
+ } else {
112
+ rest = 0;
113
+ }
114
+ }
115
+ const duration = elapsed * frame * 1000;
116
+ cache.springs[string] = duration;
117
+ return duration;
118
+ }
119
+
120
+ return duration ? solver : getDuration;
121
+
122
+ }
123
+
124
+ // Basic steps easing implementation https://developer.mozilla.org/fr/docs/Web/CSS/transition-timing-function
125
+
126
+ function steps(steps = 10) {
127
+ return t => Math.ceil((minMax(t, 0.000001, 1)) * steps) * (1 / steps);
128
+ }
129
+
130
+ // BezierEasing https://github.com/gre/bezier-easing
131
+
132
+ const bezier = (() => {
133
+
134
+ const kSplineTableSize = 11;
135
+ const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
136
+
137
+ function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1 };
138
+ function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1 };
139
+ function C(aA1) { return 3.0 * aA1 };
140
+
141
+ function calcBezier(aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT };
142
+ function getSlope(aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1) };
143
+
144
+ function binarySubdivide(aX, aA, aB, mX1, mX2) {
145
+ let currentX, currentT, i = 0;
146
+ do {
147
+ currentT = aA + (aB - aA) / 2.0;
148
+ currentX = calcBezier(currentT, mX1, mX2) - aX;
149
+ if (currentX > 0.0) { aB = currentT } else { aA = currentT };
150
+ } while (Math.abs(currentX) > 0.0000001 && ++i < 10);
151
+ return currentT;
152
+ }
153
+
154
+ function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
155
+ for (let i = 0; i < 4; ++i) {
156
+ const currentSlope = getSlope(aGuessT, mX1, mX2);
157
+ if (currentSlope === 0.0) return aGuessT;
158
+ const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
159
+ aGuessT -= currentX / currentSlope;
160
+ }
161
+ return aGuessT;
162
+ }
163
+
164
+ function bezier(mX1, mY1, mX2, mY2) {
165
+
166
+ if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) return;
167
+ let sampleValues = new Float32Array(kSplineTableSize);
168
+
169
+ if (mX1 !== mY1 || mX2 !== mY2) {
170
+ for (let i = 0; i < kSplineTableSize; ++i) {
171
+ sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
172
+ }
173
+ }
174
+
175
+ function getTForX(aX) {
176
+
177
+ let intervalStart = 0;
178
+ let currentSample = 1;
179
+ const lastSample = kSplineTableSize - 1;
180
+
181
+ for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
182
+ intervalStart += kSampleStepSize;
183
+ }
184
+
185
+ --currentSample;
186
+
187
+ const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
188
+ const guessForT = intervalStart + dist * kSampleStepSize;
189
+ const initialSlope = getSlope(guessForT, mX1, mX2);
190
+
191
+ if (initialSlope >= 0.001) {
192
+ return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
193
+ } else if (initialSlope === 0.0) {
194
+ return guessForT;
195
+ } else {
196
+ return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
197
+ }
198
+
199
+ }
200
+
201
+ return x => {
202
+ if (mX1 === mY1 && mX2 === mY2) return x;
203
+ if (x === 0 || x === 1) return x;
204
+ return calcBezier(getTForX(x), mY1, mY2);
205
+ }
206
+
207
+ }
208
+
209
+ return bezier;
210
+
211
+ })();
212
+
213
+ const penner = (() => {
214
+
215
+ // Based on jQuery UI's implemenation of easing equations from Robert Penner (http://www.robertpenner.com/easing)
216
+
217
+ const eases = { linear: () => t => t };
218
+
219
+ const functionEasings = {
220
+ Sine: () => t => 1 - Math.cos(t * Math.PI / 2),
221
+ Circ: () => t => 1 - Math.sqrt(1 - t * t),
222
+ Back: () => t => t * t * (3 * t - 2),
223
+ Bounce: () => t => {
224
+ let pow2, b = 4;
225
+ while (t < (( pow2 = Math.pow(2, --b)) - 1) / 11) {};
226
+ return 1 / Math.pow(4, 3 - b) - 7.5625 * Math.pow(( pow2 * 3 - 2 ) / 22 - t, 2)
227
+ },
228
+ Elastic: (amplitude = 1, period = .5) => {
229
+ const a = minMax(amplitude, 1, 10);
230
+ const p = minMax(period, .1, 2);
231
+ return t => {
232
+ return (t === 0 || t === 1) ? t :
233
+ -a * Math.pow(2, 10 * (t - 1)) * Math.sin((((t - 1) - (p / (Math.PI * 2) * Math.asin(1 / a))) * (Math.PI * 2)) / p);
234
+ }
235
+ }
236
+ }
237
+
238
+ const baseEasings = ['Quad', 'Cubic', 'Quart', 'Quint', 'Expo'];
239
+
240
+ baseEasings.forEach((name, i) => {
241
+ functionEasings[name] = () => t => Math.pow(t, i + 2);
242
+ });
243
+
244
+ Object.keys(functionEasings).forEach(name => {
245
+ const easeIn = functionEasings[name];
246
+ eases['easeIn' + name] = easeIn;
247
+ eases['easeOut' + name] = (a, b) => t => 1 - easeIn(a, b)(1 - t);
248
+ eases['easeInOut' + name] = (a, b) => t => t < 0.5 ? easeIn(a, b)(t * 2) / 2 :
249
+ 1 - easeIn(a, b)(t * -2 + 2) / 2;
250
+ eases['easeOutIn' + name] = (a, b) => t => t < 0.5 ? (1 - easeIn(a, b)(1 - t * 2)) / 2 :
251
+ (easeIn(a, b)(t * 2 - 1) + 1) / 2;
252
+ });
253
+
254
+ return eases;
255
+
256
+ })();
257
+
258
+ function parseEasings(easing, duration) {
259
+ if (is.fnc(easing)) return easing;
260
+ const name = easing.split('(')[0];
261
+ const ease = penner[name];
262
+ const args = parseEasingParameters(easing);
263
+ switch (name) {
264
+ case 'spring' : return spring(easing, duration);
265
+ case 'cubicBezier' : return applyArguments(bezier, args);
266
+ case 'steps' : return applyArguments(steps, args);
267
+ default : return applyArguments(ease, args);
268
+ }
269
+ }
270
+
271
+ // Strings
272
+
273
+ function selectString(str) {
274
+ try {
275
+ let nodes = document.querySelectorAll(str);
276
+ return nodes;
277
+ } catch(e) {
278
+ return;
279
+ }
280
+ }
281
+
282
+ // Arrays
283
+
284
+ function filterArray(arr, callback) {
285
+ const len = arr.length;
286
+ const thisArg = arguments.length >= 2 ? arguments[1] : void 0;
287
+ const result = [];
288
+ for (let i = 0; i < len; i++) {
289
+ if (i in arr) {
290
+ const val = arr[i];
291
+ if (callback.call(thisArg, val, i, arr)) {
292
+ result.push(val);
293
+ }
294
+ }
295
+ }
296
+ return result;
297
+ }
298
+
299
+ function flattenArray(arr) {
300
+ return arr.reduce((a, b) => a.concat(is.arr(b) ? flattenArray(b) : b), []);
301
+ }
302
+
303
+ function toArray(o) {
304
+ if (is.arr(o)) return o;
305
+ if (is.str(o)) o = selectString(o) || o;
306
+ if (o instanceof NodeList || o instanceof HTMLCollection) return [].slice.call(o);
307
+ return [o];
308
+ }
309
+
310
+ function arrayContains(arr, val) {
311
+ return arr.some(a => a === val);
312
+ }
313
+
314
+ // Objects
315
+
316
+ function cloneObject(o) {
317
+ const clone = {};
318
+ for (let p in o) clone[p] = o[p];
319
+ return clone;
320
+ }
321
+
322
+ function replaceObjectProps(o1, o2) {
323
+ const o = cloneObject(o1);
324
+ for (let p in o1) o[p] = o2.hasOwnProperty(p) ? o2[p] : o1[p];
325
+ return o;
326
+ }
327
+
328
+ function mergeObjects(o1, o2) {
329
+ const o = cloneObject(o1);
330
+ for (let p in o2) o[p] = is.und(o1[p]) ? o2[p] : o1[p];
331
+ return o;
332
+ }
333
+
334
+ // Colors
335
+
336
+ function rgbToRgba(rgbValue) {
337
+ const rgb = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(rgbValue);
338
+ return rgb ? `rgba(${rgb[1]},1)` : rgbValue;
339
+ }
340
+
341
+ function hexToRgba(hexValue) {
342
+ const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
343
+ const hex = hexValue.replace(rgx, (m, r, g, b) => r + r + g + g + b + b );
344
+ const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
345
+ const r = parseInt(rgb[1], 16);
346
+ const g = parseInt(rgb[2], 16);
347
+ const b = parseInt(rgb[3], 16);
348
+ return `rgba(${r},${g},${b},1)`;
349
+ }
350
+
351
+ function hslToRgba(hslValue) {
352
+ const hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hslValue) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(hslValue);
353
+ const h = parseInt(hsl[1], 10) / 360;
354
+ const s = parseInt(hsl[2], 10) / 100;
355
+ const l = parseInt(hsl[3], 10) / 100;
356
+ const a = hsl[4] || 1;
357
+ function hue2rgb(p, q, t) {
358
+ if (t < 0) t += 1;
359
+ if (t > 1) t -= 1;
360
+ if (t < 1/6) return p + (q - p) * 6 * t;
361
+ if (t < 1/2) return q;
362
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
363
+ return p;
364
+ }
365
+ let r, g, b;
366
+ if (s == 0) {
367
+ r = g = b = l;
368
+ } else {
369
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
370
+ const p = 2 * l - q;
371
+ r = hue2rgb(p, q, h + 1/3);
372
+ g = hue2rgb(p, q, h);
373
+ b = hue2rgb(p, q, h - 1/3);
374
+ }
375
+ return `rgba(${r * 255},${g * 255},${b * 255},${a})`;
376
+ }
377
+
378
+ function colorToRgb(val) {
379
+ if (is.rgb(val)) return rgbToRgba(val);
380
+ if (is.hex(val)) return hexToRgba(val);
381
+ if (is.hsl(val)) return hslToRgba(val);
382
+ }
383
+
384
+ // Units
385
+
386
+ function getUnit(val) {
387
+ const split = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(val);
388
+ if (split) return split[1];
389
+ }
390
+
391
+ function getTransformUnit(propName) {
392
+ if (stringContains(propName, 'translate') || propName === 'perspective') return 'px';
393
+ if (stringContains(propName, 'rotate') || stringContains(propName, 'skew')) return 'deg';
394
+ }
395
+
396
+ // Values
397
+
398
+ function getFunctionValue(val, animatable) {
399
+ if (!is.fnc(val)) return val;
400
+ return val(animatable.target, animatable.id, animatable.total);
401
+ }
402
+
403
+ function getAttribute(el, prop) {
404
+ return el.getAttribute(prop);
405
+ }
406
+
407
+ function convertPxToUnit(el, value, unit) {
408
+ const valueUnit = getUnit(value);
409
+ if (arrayContains([unit, 'deg', 'rad', 'turn'], valueUnit)) return value;
410
+ const cached = cache.CSS[value + unit];
411
+ if (!is.und(cached)) return cached;
412
+ const baseline = 100;
413
+ const tempEl = document.createElement(el.tagName);
414
+ const parentEl = (el.parentNode && (el.parentNode !== document)) ? el.parentNode : document.body;
415
+ parentEl.appendChild(tempEl);
416
+ tempEl.style.position = 'absolute';
417
+ tempEl.style.width = baseline + unit;
418
+ const factor = baseline / tempEl.offsetWidth;
419
+ parentEl.removeChild(tempEl);
420
+ const convertedUnit = factor * parseFloat(value);
421
+ cache.CSS[value + unit] = convertedUnit;
422
+ return convertedUnit;
423
+ }
424
+
425
+ function getCSSValue(el, prop, unit) {
426
+ if (prop in el.style) {
427
+ const uppercasePropName = prop.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
428
+ const value = el.style[prop] || getComputedStyle(el).getPropertyValue(uppercasePropName) || '0';
429
+ return unit ? convertPxToUnit(el, value, unit) : value;
430
+ }
431
+ }
432
+
433
+ function getAnimationType(el, prop) {
434
+ if (is.dom(el) && !is.inp(el) && (!is.nil(getAttribute(el, prop)) || (is.svg(el) && el[prop]))) return 'attribute';
435
+ if (is.dom(el) && arrayContains(validTransforms, prop)) return 'transform';
436
+ if (is.dom(el) && (prop !== 'transform' && getCSSValue(el, prop))) return 'css';
437
+ if (el[prop] != null) return 'object';
438
+ }
439
+
440
+ function getElementTransforms(el) {
441
+ if (!is.dom(el)) return;
442
+ const str = el.style.transform || '';
443
+ const reg = /(\w+)\(([^)]*)\)/g;
444
+ const transforms = new Map();
445
+ let m; while (m = reg.exec(str)) transforms.set(m[1], m[2]);
446
+ return transforms;
447
+ }
448
+
449
+ function getTransformValue(el, propName, animatable, unit) {
450
+ const defaultVal = stringContains(propName, 'scale') ? 1 : 0 + getTransformUnit(propName);
451
+ const value = getElementTransforms(el).get(propName) || defaultVal;
452
+ if (animatable) {
453
+ animatable.transforms.list.set(propName, value);
454
+ animatable.transforms['last'] = propName;
455
+ }
456
+ return unit ? convertPxToUnit(el, value, unit) : value;
457
+ }
458
+
459
+ function getOriginalTargetValue(target, propName, unit, animatable) {
460
+ switch (getAnimationType(target, propName)) {
461
+ case 'transform': return getTransformValue(target, propName, animatable, unit);
462
+ case 'css': return getCSSValue(target, propName, unit);
463
+ case 'attribute': return getAttribute(target, propName);
464
+ default: return target[propName] || 0;
465
+ }
466
+ }
467
+
468
+ function getRelativeValue(to, from) {
469
+ const operator = /^(\*=|\+=|-=)/.exec(to);
470
+ if (!operator) return to;
471
+ const u = getUnit(to) || 0;
472
+ const x = parseFloat(from);
473
+ const y = parseFloat(to.replace(operator[0], ''));
474
+ switch (operator[0][0]) {
475
+ case '+': return x + y + u;
476
+ case '-': return x - y + u;
477
+ case '*': return x * y + u;
478
+ }
479
+ }
480
+
481
+ function validateValue(val, unit) {
482
+ if (is.col(val)) return colorToRgb(val);
483
+ if (/\s/g.test(val)) return val;
484
+ const originalUnit = getUnit(val);
485
+ const unitLess = originalUnit ? val.substr(0, val.length - originalUnit.length) : val;
486
+ if (unit) return unitLess + unit;
487
+ return unitLess;
488
+ }
489
+
490
+ // getTotalLength() equivalent for circle, rect, polyline, polygon and line shapes
491
+ // adapted from https://gist.github.com/SebLambla/3e0550c496c236709744
492
+
493
+ function getDistance(p1, p2) {
494
+ return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
495
+ }
496
+
497
+ function getCircleLength(el) {
498
+ return Math.PI * 2 * getAttribute(el, 'r');
499
+ }
500
+
501
+ function getRectLength(el) {
502
+ return (getAttribute(el, 'width') * 2) + (getAttribute(el, 'height') * 2);
503
+ }
504
+
505
+ function getLineLength(el) {
506
+ return getDistance(
507
+ {x: getAttribute(el, 'x1'), y: getAttribute(el, 'y1')},
508
+ {x: getAttribute(el, 'x2'), y: getAttribute(el, 'y2')}
509
+ );
510
+ }
511
+
512
+ function getPolylineLength(el) {
513
+ const points = el.points;
514
+ let totalLength = 0;
515
+ let previousPos;
516
+ for (let i = 0 ; i < points.numberOfItems; i++) {
517
+ const currentPos = points.getItem(i);
518
+ if (i > 0) totalLength += getDistance(previousPos, currentPos);
519
+ previousPos = currentPos;
520
+ }
521
+ return totalLength;
522
+ }
523
+
524
+ function getPolygonLength(el) {
525
+ const points = el.points;
526
+ return getPolylineLength(el) + getDistance(points.getItem(points.numberOfItems - 1), points.getItem(0));
527
+ }
528
+
529
+ // Path animation
530
+
531
+ function getTotalLength(el) {
532
+ if (el.getTotalLength) return el.getTotalLength();
533
+ switch(el.tagName.toLowerCase()) {
534
+ case 'circle': return getCircleLength(el);
535
+ case 'rect': return getRectLength(el);
536
+ case 'line': return getLineLength(el);
537
+ case 'polyline': return getPolylineLength(el);
538
+ case 'polygon': return getPolygonLength(el);
539
+ }
540
+ }
541
+
542
+ function setDashoffset(el) {
543
+ const pathLength = getTotalLength(el);
544
+ el.setAttribute('stroke-dasharray', pathLength);
545
+ return pathLength;
546
+ }
547
+
548
+ // Motion path
549
+
550
+ function getParentSvgEl(el) {
551
+ let parentEl = el.parentNode;
552
+ while (is.svg(parentEl)) {
553
+ if (!is.svg(parentEl.parentNode)) break;
554
+ parentEl = parentEl.parentNode;
555
+ }
556
+ return parentEl;
557
+ }
558
+
559
+ function getParentSvg(pathEl, svgData) {
560
+ const svg = svgData || {};
561
+ const parentSvgEl = svg.el || getParentSvgEl(pathEl);
562
+ const rect = parentSvgEl.getBoundingClientRect();
563
+ const viewBoxAttr = getAttribute(parentSvgEl, 'viewBox');
564
+ const width = rect.width;
565
+ const height = rect.height;
566
+ const viewBox = svg.viewBox || (viewBoxAttr ? viewBoxAttr.split(' ') : [0, 0, width, height]);
567
+ return {
568
+ el: parentSvgEl,
569
+ viewBox: viewBox,
570
+ x: viewBox[0] / 1,
571
+ y: viewBox[1] / 1,
572
+ w: width,
573
+ h: height,
574
+ vW: viewBox[2],
575
+ vH: viewBox[3]
576
+ }
577
+ }
578
+
579
+ function getPath(path, percent) {
580
+ const pathEl = is.str(path) ? selectString(path)[0] : path;
581
+ const p = percent || 100;
582
+ return function(property) {
583
+ return {
584
+ property,
585
+ el: pathEl,
586
+ svg: getParentSvg(pathEl),
587
+ totalLength: getTotalLength(pathEl) * (p / 100)
588
+ }
589
+ }
590
+ }
591
+
592
+ function getPathProgress(path, progress, isPathTargetInsideSVG) {
593
+ function point(offset = 0) {
594
+ const l = progress + offset >= 1 ? progress + offset : 0;
595
+ return path.el.getPointAtLength(l);
596
+ }
597
+ const svg = getParentSvg(path.el, path.svg)
598
+ const p = point();
599
+ const p0 = point(-1);
600
+ const p1 = point(+1);
601
+ const scaleX = isPathTargetInsideSVG ? 1 : svg.w / svg.vW;
602
+ const scaleY = isPathTargetInsideSVG ? 1 : svg.h / svg.vH;
603
+ switch (path.property) {
604
+ case 'x': return (p.x - svg.x) * scaleX;
605
+ case 'y': return (p.y - svg.y) * scaleY;
606
+ case 'angle': return Math.atan2(p1.y - p0.y, p1.x - p0.x) * 180 / Math.PI;
607
+ }
608
+ }
609
+
610
+ // Decompose value
611
+
612
+ function decomposeValue(val, unit) {
613
+ // const rgx = /-?\d*\.?\d+/g; // handles basic numbers
614
+ // const rgx = /[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g; // handles exponents notation
615
+ const rgx = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g; // handles exponents notation
616
+ const value = validateValue((is.pth(val) ? val.totalLength : val), unit) + '';
617
+ return {
618
+ original: value,
619
+ numbers: value.match(rgx) ? value.match(rgx).map(Number) : [0],
620
+ strings: (is.str(val) || unit) ? value.split(rgx) : []
621
+ }
622
+ }
623
+
624
+ // Animatables
625
+
626
+ function parseTargets(targets) {
627
+ const targetsArray = targets ? (flattenArray(is.arr(targets) ? targets.map(toArray) : toArray(targets))) : [];
628
+ return filterArray(targetsArray, (item, pos, self) => self.indexOf(item) === pos);
629
+ }
630
+
631
+ function getAnimatables(targets) {
632
+ const parsed = parseTargets(targets);
633
+ return parsed.map((t, i) => {
634
+ return {target: t, id: i, total: parsed.length, transforms: { list: getElementTransforms(t) } };
635
+ });
636
+ }
637
+
638
+ // Properties
639
+
640
+ function normalizePropertyTweens(prop, tweenSettings) {
641
+ let settings = cloneObject(tweenSettings);
642
+ // Override duration if easing is a spring
643
+ if (/^spring/.test(settings.easing)) settings.duration = spring(settings.easing);
644
+ if (is.arr(prop)) {
645
+ const l = prop.length;
646
+ const isFromTo = (l === 2 && !is.obj(prop[0]));
647
+ if (!isFromTo) {
648
+ // Duration divided by the number of tweens
649
+ if (!is.fnc(tweenSettings.duration)) settings.duration = tweenSettings.duration / l;
650
+ } else {
651
+ // Transform [from, to] values shorthand to a valid tween value
652
+ prop = {value: prop};
653
+ }
654
+ }
655
+ const propArray = is.arr(prop) ? prop : [prop];
656
+ return propArray.map((v, i) => {
657
+ const obj = (is.obj(v) && !is.pth(v)) ? v : {value: v};
658
+ // Default delay value should only be applied to the first tween
659
+ if (is.und(obj.delay)) obj.delay = !i ? tweenSettings.delay : 0;
660
+ // Default endDelay value should only be applied to the last tween
661
+ if (is.und(obj.endDelay)) obj.endDelay = i === propArray.length - 1 ? tweenSettings.endDelay : 0;
662
+ return obj;
663
+ }).map(k => mergeObjects(k, settings));
664
+ }
665
+
666
+
667
+ function flattenKeyframes(keyframes) {
668
+ const propertyNames = filterArray(flattenArray(keyframes.map(key => Object.keys(key))), p => is.key(p))
669
+ .reduce((a,b) => { if (a.indexOf(b) < 0) a.push(b); return a; }, []);
670
+ const properties = {};
671
+ for (let i = 0; i < propertyNames.length; i++) {
672
+ const propName = propertyNames[i];
673
+ properties[propName] = keyframes.map(key => {
674
+ const newKey = {};
675
+ for (let p in key) {
676
+ if (is.key(p)) {
677
+ if (p == propName) newKey.value = key[p];
678
+ } else {
679
+ newKey[p] = key[p];
680
+ }
681
+ }
682
+ return newKey;
683
+ });
684
+ }
685
+ return properties;
686
+ }
687
+
688
+ function getProperties(tweenSettings, params) {
689
+ const properties = [];
690
+ const keyframes = params.keyframes;
691
+ if (keyframes) params = mergeObjects(flattenKeyframes(keyframes), params);;
692
+ for (let p in params) {
693
+ if (is.key(p)) {
694
+ properties.push({
695
+ name: p,
696
+ tweens: normalizePropertyTweens(params[p], tweenSettings)
697
+ });
698
+ }
699
+ }
700
+ return properties;
701
+ }
702
+
703
+ // Tweens
704
+
705
+ function normalizeTweenValues(tween, animatable) {
706
+ const t = {};
707
+ for (let p in tween) {
708
+ let value = getFunctionValue(tween[p], animatable);
709
+ if (is.arr(value)) {
710
+ value = value.map(v => getFunctionValue(v, animatable));
711
+ if (value.length === 1) value = value[0];
712
+ }
713
+ t[p] = value;
714
+ }
715
+ t.duration = parseFloat(t.duration);
716
+ t.delay = parseFloat(t.delay);
717
+ return t;
718
+ }
719
+
720
+ function normalizeTweens(prop, animatable) {
721
+ let previousTween;
722
+ return prop.tweens.map(t => {
723
+ const tween = normalizeTweenValues(t, animatable);
724
+ const tweenValue = tween.value;
725
+ let to = is.arr(tweenValue) ? tweenValue[1] : tweenValue;
726
+ const toUnit = getUnit(to);
727
+ const originalValue = getOriginalTargetValue(animatable.target, prop.name, toUnit, animatable);
728
+ const previousValue = previousTween ? previousTween.to.original : originalValue;
729
+ const from = is.arr(tweenValue) ? tweenValue[0] : previousValue;
730
+ const fromUnit = getUnit(from) || getUnit(originalValue);
731
+ const unit = toUnit || fromUnit;
732
+ if (is.und(to)) to = previousValue;
733
+ tween.from = decomposeValue(from, unit);
734
+ tween.to = decomposeValue(getRelativeValue(to, from), unit);
735
+ tween.start = previousTween ? previousTween.end : 0;
736
+ tween.end = tween.start + tween.delay + tween.duration + tween.endDelay;
737
+ tween.easing = parseEasings(tween.easing, tween.duration);
738
+ tween.isPath = is.pth(tweenValue);
739
+ tween.isPathTargetInsideSVG = tween.isPath && is.svg(animatable.target);
740
+ tween.isColor = is.col(tween.from.original);
741
+ if (tween.isColor) tween.round = 1;
742
+ previousTween = tween;
743
+ return tween;
744
+ });
745
+ }
746
+
747
+ // Tween progress
748
+
749
+ const setProgressValue = {
750
+ css: (t, p, v) => t.style[p] = v,
751
+ attribute: (t, p, v) => t.setAttribute(p, v),
752
+ object: (t, p, v) => t[p] = v,
753
+ transform: (t, p, v, transforms, manual) => {
754
+ transforms.list.set(p, v);
755
+ if (p === transforms.last || manual) {
756
+ let str = '';
757
+ transforms.list.forEach((value, prop) => { str += `${prop}(${value}) `; });
758
+ t.style.transform = str;
759
+ }
760
+ }
761
+ }
762
+
763
+ // Set Value helper
764
+
765
+ function setTargetsValue(targets, properties) {
766
+ const animatables = getAnimatables(targets);
767
+ animatables.forEach(animatable => {
768
+ for (let property in properties) {
769
+ const value = getFunctionValue(properties[property], animatable);
770
+ const target = animatable.target;
771
+ const valueUnit = getUnit(value);
772
+ const originalValue = getOriginalTargetValue(target, property, valueUnit, animatable);
773
+ const unit = valueUnit || getUnit(originalValue);
774
+ const to = getRelativeValue(validateValue(value, unit), originalValue);
775
+ const animType = getAnimationType(target, property);
776
+ setProgressValue[animType](target, property, to, animatable.transforms, true);
777
+ }
778
+ });
779
+ }
780
+
781
+ // Animations
782
+
783
+ function createAnimation(animatable, prop) {
784
+ const animType = getAnimationType(animatable.target, prop.name);
785
+ if (animType) {
786
+ const tweens = normalizeTweens(prop, animatable);
787
+ const lastTween = tweens[tweens.length - 1];
788
+ return {
789
+ type: animType,
790
+ property: prop.name,
791
+ animatable: animatable,
792
+ tweens: tweens,
793
+ duration: lastTween.end,
794
+ delay: tweens[0].delay,
795
+ endDelay: lastTween.endDelay
796
+ }
797
+ }
798
+ }
799
+
800
+ function getAnimations(animatables, properties) {
801
+ return filterArray(flattenArray(animatables.map(animatable => {
802
+ return properties.map(prop => {
803
+ return createAnimation(animatable, prop);
804
+ });
805
+ })), a => !is.und(a));
806
+ }
807
+
808
+ // Create Instance
809
+
810
+ function getInstanceTimings(animations, tweenSettings) {
811
+ const animLength = animations.length;
812
+ const getTlOffset = anim => anim.timelineOffset ? anim.timelineOffset : 0;
813
+ const timings = {};
814
+ timings.duration = animLength ? Math.max.apply(Math, animations.map(anim => getTlOffset(anim) + anim.duration)) : tweenSettings.duration;
815
+ timings.delay = animLength ? Math.min.apply(Math, animations.map(anim => getTlOffset(anim) + anim.delay)) : tweenSettings.delay;
816
+ timings.endDelay = animLength ? timings.duration - Math.max.apply(Math, animations.map(anim => getTlOffset(anim) + anim.duration - anim.endDelay)) : tweenSettings.endDelay;
817
+ return timings;
818
+ }
819
+
820
+ let instanceID = 0;
821
+
822
+ function createNewInstance(params) {
823
+ const instanceSettings = replaceObjectProps(defaultInstanceSettings, params);
824
+ const tweenSettings = replaceObjectProps(defaultTweenSettings, params);
825
+ const properties = getProperties(tweenSettings, params);
826
+ const animatables = getAnimatables(params.targets);
827
+ const animations = getAnimations(animatables, properties);
828
+ const timings = getInstanceTimings(animations, tweenSettings);
829
+ const id = instanceID;
830
+ instanceID++;
831
+ return mergeObjects(instanceSettings, {
832
+ id: id,
833
+ children: [],
834
+ animatables: animatables,
835
+ animations: animations,
836
+ duration: timings.duration,
837
+ delay: timings.delay,
838
+ endDelay: timings.endDelay
839
+ });
840
+ }
841
+
842
+ // Core
843
+
844
+ let activeInstances = [];
845
+
846
+ const engine = (() => {
847
+ let raf;
848
+
849
+ function play() {
850
+ if (!raf && (!isDocumentHidden() || !anime.suspendWhenDocumentHidden) && activeInstances.length > 0) {
851
+ raf = requestAnimationFrame(step);
852
+ }
853
+ }
854
+ function step(t) {
855
+ // memo on algorithm issue:
856
+ // dangerous iteration over mutable `activeInstances`
857
+ // (that collection may be updated from within callbacks of `tick`-ed animation instances)
858
+ let activeInstancesLength = activeInstances.length;
859
+ let i = 0;
860
+ while (i < activeInstancesLength) {
861
+ const activeInstance = activeInstances[i];
862
+ if (!activeInstance.paused) {
863
+ activeInstance.tick(t);
864
+ i++;
865
+ } else {
866
+ activeInstances.splice(i, 1);
867
+ activeInstancesLength--;
868
+ }
869
+ }
870
+ raf = i > 0 ? requestAnimationFrame(step) : undefined;
871
+ }
872
+
873
+ function handleVisibilityChange() {
874
+ if (!anime.suspendWhenDocumentHidden) return;
875
+
876
+ if (isDocumentHidden()) {
877
+ // suspend ticks
878
+ raf = cancelAnimationFrame(raf);
879
+ } else { // is back to active tab
880
+ // first adjust animations to consider the time that ticks were suspended
881
+ activeInstances.forEach(
882
+ instance => instance ._onDocumentVisibility()
883
+ );
884
+ engine();
885
+ }
886
+ }
887
+ if (typeof document !== 'undefined') {
888
+ document.addEventListener('visibilitychange', handleVisibilityChange);
889
+ }
890
+
891
+ return play;
892
+ })();
893
+
894
+ function isDocumentHidden() {
895
+ return !!document && document.hidden;
896
+ }
897
+
898
+ // Public Instance
899
+
900
+ function anime(params = {}) {
901
+
902
+ let startTime = 0, lastTime = 0, now = 0;
903
+ let children, childrenLength = 0;
904
+ let resolve = null;
905
+
906
+ function makePromise(instance) {
907
+ const promise = window.Promise && new Promise(_resolve => resolve = _resolve);
908
+ instance.finished = promise;
909
+ return promise;
910
+ }
911
+
912
+ let instance = createNewInstance(params);
913
+ let promise = makePromise(instance);
914
+
915
+ function toggleInstanceDirection() {
916
+ const direction = instance.direction;
917
+ if (direction !== 'alternate') {
918
+ instance.direction = direction !== 'normal' ? 'normal' : 'reverse';
919
+ }
920
+ instance.reversed = !instance.reversed;
921
+ children.forEach(child => child.reversed = instance.reversed);
922
+ }
923
+
924
+ function adjustTime(time) {
925
+ return instance.reversed ? instance.duration - time : time;
926
+ }
927
+
928
+ function resetTime() {
929
+ startTime = 0;
930
+ lastTime = adjustTime(instance.currentTime) * (1 / anime.speed);
931
+ }
932
+
933
+ function seekChild(time, child) {
934
+ if (child) child.seek(time - child.timelineOffset);
935
+ }
936
+
937
+ function syncInstanceChildren(time) {
938
+ if (!instance.reversePlayback) {
939
+ for (let i = 0; i < childrenLength; i++) seekChild(time, children[i]);
940
+ } else {
941
+ for (let i = childrenLength; i--;) seekChild(time, children[i]);
942
+ }
943
+ }
944
+
945
+ function setAnimationsProgress(insTime) {
946
+ let i = 0;
947
+ const animations = instance.animations;
948
+ const animationsLength = animations.length;
949
+ while (i < animationsLength) {
950
+ const anim = animations[i];
951
+ const animatable = anim.animatable;
952
+ const tweens = anim.tweens;
953
+ const tweenLength = tweens.length - 1;
954
+ let tween = tweens[tweenLength];
955
+ // Only check for keyframes if there is more than one tween
956
+ if (tweenLength) tween = filterArray(tweens, t => (insTime < t.end))[0] || tween;
957
+ const elapsed = minMax(insTime - tween.start - tween.delay, 0, tween.duration) / tween.duration;
958
+ const eased = isNaN(elapsed) ? 1 : tween.easing(elapsed);
959
+ const strings = tween.to.strings;
960
+ const round = tween.round;
961
+ const numbers = [];
962
+ const toNumbersLength = tween.to.numbers.length;
963
+ let progress;
964
+ for (let n = 0; n < toNumbersLength; n++) {
965
+ let value;
966
+ const toNumber = tween.to.numbers[n];
967
+ const fromNumber = tween.from.numbers[n] || 0;
968
+ if (!tween.isPath) {
969
+ value = fromNumber + (eased * (toNumber - fromNumber));
970
+ } else {
971
+ value = getPathProgress(tween.value, eased * toNumber, tween.isPathTargetInsideSVG);
972
+ }
973
+ if (round) {
974
+ if (!(tween.isColor && n > 2)) {
975
+ value = Math.round(value * round) / round;
976
+ }
977
+ }
978
+ numbers.push(value);
979
+ }
980
+ // Manual Array.reduce for better performances
981
+ const stringsLength = strings.length;
982
+ if (!stringsLength) {
983
+ progress = numbers[0];
984
+ } else {
985
+ progress = strings[0];
986
+ for (let s = 0; s < stringsLength; s++) {
987
+ const a = strings[s];
988
+ const b = strings[s + 1];
989
+ const n = numbers[s];
990
+ if (!isNaN(n)) {
991
+ if (!b) {
992
+ progress += n + ' ';
993
+ } else {
994
+ progress += n + b;
995
+ }
996
+ }
997
+ }
998
+ }
999
+ setProgressValue[anim.type](animatable.target, anim.property, progress, animatable.transforms);
1000
+ anim.currentValue = progress;
1001
+ i++;
1002
+ }
1003
+ }
1004
+
1005
+ function setCallback(cb) {
1006
+ if (instance[cb] && !instance.passThrough) instance[cb](instance);
1007
+ }
1008
+
1009
+ function countIteration() {
1010
+ if (instance.remaining && instance.remaining !== true) {
1011
+ instance.remaining--;
1012
+ }
1013
+ }
1014
+
1015
+ function setInstanceProgress(engineTime) {
1016
+ const insDuration = instance.duration;
1017
+ const insDelay = instance.delay;
1018
+ const insEndDelay = insDuration - instance.endDelay;
1019
+ const insTime = adjustTime(engineTime);
1020
+ instance.progress = minMax((insTime / insDuration) * 100, 0, 100);
1021
+ instance.reversePlayback = insTime < instance.currentTime;
1022
+ if (children) { syncInstanceChildren(insTime); }
1023
+ if (!instance.began && instance.currentTime > 0) {
1024
+ instance.began = true;
1025
+ setCallback('begin');
1026
+ }
1027
+ if (!instance.loopBegan && instance.currentTime > 0) {
1028
+ instance.loopBegan = true;
1029
+ setCallback('loopBegin');
1030
+ }
1031
+ if (insTime <= insDelay && instance.currentTime !== 0) {
1032
+ setAnimationsProgress(0);
1033
+ }
1034
+ if ((insTime >= insEndDelay && instance.currentTime !== insDuration) || !insDuration) {
1035
+ setAnimationsProgress(insDuration);
1036
+ }
1037
+ if (insTime > insDelay && insTime < insEndDelay) {
1038
+ if (!instance.changeBegan) {
1039
+ instance.changeBegan = true;
1040
+ instance.changeCompleted = false;
1041
+ setCallback('changeBegin');
1042
+ }
1043
+ setCallback('change');
1044
+ setAnimationsProgress(insTime);
1045
+ } else {
1046
+ if (instance.changeBegan) {
1047
+ instance.changeCompleted = true;
1048
+ instance.changeBegan = false;
1049
+ setCallback('changeComplete');
1050
+ }
1051
+ }
1052
+ instance.currentTime = minMax(insTime, 0, insDuration);
1053
+ if (instance.began) setCallback('update');
1054
+ if (engineTime >= insDuration) {
1055
+ lastTime = 0;
1056
+ countIteration();
1057
+ if (!instance.remaining) {
1058
+ instance.paused = true;
1059
+ if (!instance.completed) {
1060
+ instance.completed = true;
1061
+ setCallback('loopComplete');
1062
+ setCallback('complete');
1063
+ if (!instance.passThrough && 'Promise' in window) {
1064
+ resolve();
1065
+ promise = makePromise(instance);
1066
+ }
1067
+ }
1068
+ } else {
1069
+ startTime = now;
1070
+ setCallback('loopComplete');
1071
+ instance.loopBegan = false;
1072
+ if (instance.direction === 'alternate') {
1073
+ toggleInstanceDirection();
1074
+ }
1075
+ }
1076
+ }
1077
+ }
1078
+
1079
+ instance.reset = function() {
1080
+ const direction = instance.direction;
1081
+ instance.passThrough = false;
1082
+ instance.currentTime = 0;
1083
+ instance.progress = 0;
1084
+ instance.paused = true;
1085
+ instance.began = false;
1086
+ instance.loopBegan = false;
1087
+ instance.changeBegan = false;
1088
+ instance.completed = false;
1089
+ instance.changeCompleted = false;
1090
+ instance.reversePlayback = false;
1091
+ instance.reversed = direction === 'reverse';
1092
+ instance.remaining = instance.loop;
1093
+ children = instance.children;
1094
+ childrenLength = children.length;
1095
+ for (let i = childrenLength; i--;) instance.children[i].reset();
1096
+ if (instance.reversed && instance.loop !== true || (direction === 'alternate' && instance.loop === 1)) instance.remaining++;
1097
+ setAnimationsProgress(instance.reversed ? instance.duration : 0);
1098
+ }
1099
+
1100
+ // internal method (for engine) to adjust animation timings before restoring engine ticks (rAF)
1101
+ instance._onDocumentVisibility = resetTime;
1102
+
1103
+ // Set Value helper
1104
+
1105
+ instance.set = function(targets, properties) {
1106
+ setTargetsValue(targets, properties);
1107
+ return instance;
1108
+ }
1109
+
1110
+ instance.tick = function(t) {
1111
+ now = t;
1112
+ if (!startTime) startTime = now;
1113
+ setInstanceProgress((now + (lastTime - startTime)) * anime.speed);
1114
+ }
1115
+
1116
+ instance.seek = function(time) {
1117
+ setInstanceProgress(adjustTime(time));
1118
+ }
1119
+
1120
+ instance.pause = function() {
1121
+ instance.paused = true;
1122
+ resetTime();
1123
+ }
1124
+
1125
+ instance.play = function() {
1126
+ if (!instance.paused) return;
1127
+ if (instance.completed) instance.reset();
1128
+ instance.paused = false;
1129
+ activeInstances.push(instance);
1130
+ resetTime();
1131
+ engine();
1132
+ }
1133
+
1134
+ instance.reverse = function() {
1135
+ toggleInstanceDirection();
1136
+ instance.completed = instance.reversed ? false : true;
1137
+ resetTime();
1138
+ }
1139
+
1140
+ instance.restart = function() {
1141
+ instance.reset();
1142
+ instance.play();
1143
+ }
1144
+
1145
+ instance.remove = function(targets) {
1146
+ const targetsArray = parseTargets(targets);
1147
+ removeTargetsFromInstance(targetsArray, instance);
1148
+ }
1149
+
1150
+ instance.reset();
1151
+
1152
+ if (instance.autoplay) instance.play();
1153
+
1154
+ return instance;
1155
+
1156
+ }
1157
+
1158
+ // Remove targets from animation
1159
+
1160
+ function removeTargetsFromAnimations(targetsArray, animations) {
1161
+ for (let a = animations.length; a--;) {
1162
+ if (arrayContains(targetsArray, animations[a].animatable.target)) {
1163
+ animations.splice(a, 1);
1164
+ }
1165
+ }
1166
+ }
1167
+
1168
+ function removeTargetsFromInstance(targetsArray, instance) {
1169
+ const animations = instance.animations;
1170
+ const children = instance.children;
1171
+ removeTargetsFromAnimations(targetsArray, animations);
1172
+ for (let c = children.length; c--;) {
1173
+ const child = children[c];
1174
+ const childAnimations = child.animations;
1175
+ removeTargetsFromAnimations(targetsArray, childAnimations);
1176
+ if (!childAnimations.length && !child.children.length) children.splice(c, 1);
1177
+ }
1178
+ if (!animations.length && !children.length) instance.pause();
1179
+ }
1180
+
1181
+ function removeTargetsFromActiveInstances(targets) {
1182
+ const targetsArray = parseTargets(targets);
1183
+ for (let i = activeInstances.length; i--;) {
1184
+ const instance = activeInstances[i];
1185
+ removeTargetsFromInstance(targetsArray, instance);
1186
+ }
1187
+ }
1188
+
1189
+ // Stagger helpers
1190
+
1191
+ function stagger(val, params = {}) {
1192
+ const direction = params.direction || 'normal';
1193
+ const easing = params.easing ? parseEasings(params.easing) : null;
1194
+ const grid = params.grid;
1195
+ const axis = params.axis;
1196
+ let fromIndex = params.from || 0;
1197
+ const fromFirst = fromIndex === 'first';
1198
+ const fromCenter = fromIndex === 'center';
1199
+ const fromLast = fromIndex === 'last';
1200
+ const isRange = is.arr(val);
1201
+ const val1 = isRange ? parseFloat(val[0]) : parseFloat(val);
1202
+ const val2 = isRange ? parseFloat(val[1]) : 0;
1203
+ const unit = getUnit(isRange ? val[1] : val) || 0;
1204
+ const start = params.start || 0 + (isRange ? val1 : 0);
1205
+ let values = [];
1206
+ let maxValue = 0;
1207
+ return (el, i, t) => {
1208
+ if (fromFirst) fromIndex = 0;
1209
+ if (fromCenter) fromIndex = (t - 1) / 2;
1210
+ if (fromLast) fromIndex = t - 1;
1211
+ if (!values.length) {
1212
+ for (let index = 0; index < t; index++) {
1213
+ if (!grid) {
1214
+ values.push(Math.abs(fromIndex - index));
1215
+ } else {
1216
+ const fromX = !fromCenter ? fromIndex%grid[0] : (grid[0]-1)/2;
1217
+ const fromY = !fromCenter ? Math.floor(fromIndex/grid[0]) : (grid[1]-1)/2;
1218
+ const toX = index%grid[0];
1219
+ const toY = Math.floor(index/grid[0]);
1220
+ const distanceX = fromX - toX;
1221
+ const distanceY = fromY - toY;
1222
+ let value = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
1223
+ if (axis === 'x') value = -distanceX;
1224
+ if (axis === 'y') value = -distanceY;
1225
+ values.push(value);
1226
+ }
1227
+ maxValue = Math.max(...values);
1228
+ }
1229
+ if (easing) values = values.map(val => easing(val / maxValue) * maxValue);
1230
+ if (direction === 'reverse') values = values.map(val => axis ? (val < 0) ? val * -1 : -val : Math.abs(maxValue - val));
1231
+ }
1232
+ const spacing = isRange ? (val2 - val1) / maxValue : val1;
1233
+ return start + (spacing * (Math.round(values[i] * 100) / 100)) + unit;
1234
+ }
1235
+ }
1236
+
1237
+ // Timeline
1238
+
1239
+ function timeline(params = {}) {
1240
+ let tl = anime(params);
1241
+ tl.duration = 0;
1242
+ tl.add = function(instanceParams, timelineOffset) {
1243
+ const tlIndex = activeInstances.indexOf(tl);
1244
+ const children = tl.children;
1245
+ if (tlIndex > -1) activeInstances.splice(tlIndex, 1);
1246
+ function passThrough(ins) { ins.passThrough = true; };
1247
+ for (let i = 0; i < children.length; i++) passThrough(children[i]);
1248
+ let insParams = mergeObjects(instanceParams, replaceObjectProps(defaultTweenSettings, params));
1249
+ insParams.targets = insParams.targets || params.targets;
1250
+ const tlDuration = tl.duration;
1251
+ insParams.autoplay = false;
1252
+ insParams.direction = tl.direction;
1253
+ insParams.timelineOffset = is.und(timelineOffset) ? tlDuration : getRelativeValue(timelineOffset, tlDuration);
1254
+ passThrough(tl);
1255
+ tl.seek(insParams.timelineOffset);
1256
+ const ins = anime(insParams);
1257
+ passThrough(ins);
1258
+ const totalDuration = ins.duration + insParams.timelineOffset;
1259
+ children.push(ins);
1260
+ const timings = getInstanceTimings(children, params);
1261
+ tl.delay = timings.delay;
1262
+ tl.endDelay = timings.endDelay;
1263
+ tl.duration = timings.duration;
1264
+ tl.seek(0);
1265
+ tl.reset();
1266
+ if (tl.autoplay) tl.play();
1267
+ return tl;
1268
+ }
1269
+ return tl;
1270
+ }
1271
+
1272
+ anime.version = '3.2.1';
1273
+ anime.speed = 1;
1274
+ // TODO:#review: naming, documentation
1275
+ anime.suspendWhenDocumentHidden = true;
1276
+ anime.running = activeInstances;
1277
+ anime.remove = removeTargetsFromActiveInstances;
1278
+ anime.get = getOriginalTargetValue;
1279
+ anime.set = setTargetsValue;
1280
+ anime.convertPx = convertPxToUnit;
1281
+ anime.path = getPath;
1282
+ anime.setDashoffset = setDashoffset;
1283
+ anime.stagger = stagger;
1284
+ anime.timeline = timeline;
1285
+ anime.easing = parseEasings;
1286
+ anime.penner = penner;
1287
+ anime.random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
1288
+
1289
+ export default anime;