anime-rails 3.2.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;