anime.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /*
  2. * Anime v1.1.2
  3. * http://anime-js.com
  4. * JavaScript animation engine
  5. * Copyright (c) 2016 Julian Garnier
  6. * http://juliangarnier.com
  7. * Released under the MIT license
  8. */
  9. (function (root, factory) {
  10. if (typeof define === 'function' && define.amd) {
  11. // AMD. Register as an anonymous module.
  12. define([], factory);
  13. } else if (typeof module === 'object' && module.exports) {
  14. // Node. Does not work with strict CommonJS, but
  15. // only CommonJS-like environments that support module.exports,
  16. // like Node.
  17. module.exports = factory();
  18. } else {
  19. // Browser globals (root is window)
  20. root.anime = factory();
  21. }
  22. }(this, function () {
  23. var version = '1.1.2';
  24. // Defaults
  25. var defaultSettings = {
  26. duration: 1000,
  27. delay: 0,
  28. loop: false,
  29. autoplay: true,
  30. direction: 'normal',
  31. easing: 'easeOutElastic',
  32. elasticity: 400,
  33. round: false,
  34. begin: undefined,
  35. update: undefined,
  36. complete: undefined
  37. }
  38. // Transforms
  39. var validTransforms = ['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'skewX', 'skewY'];
  40. var transform, transformStr = 'transform';
  41. // Utils
  42. var is = {
  43. arr: function(a) { return Array.isArray(a) },
  44. obj: function(a) { return Object.prototype.toString.call(a).indexOf('Object') > -1 },
  45. svg: function(a) { return a instanceof SVGElement },
  46. dom: function(a) { return a.nodeType || is.svg(a) },
  47. num: function(a) { return !isNaN(parseInt(a)) },
  48. str: function(a) { return typeof a === 'string' },
  49. fnc: function(a) { return typeof a === 'function' },
  50. und: function(a) { return typeof a === 'undefined' },
  51. nul: function(a) { return typeof a === 'null' },
  52. hex: function(a) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a) },
  53. rgb: function(a) { return /^rgb/.test(a) },
  54. hsl: function(a) { return /^hsl/.test(a) },
  55. col: function(a) { return (is.hex(a) || is.rgb(a) || is.hsl(a)) }
  56. }
  57. // Easings functions adapted from http://jqueryui.com/
  58. var easings = (function() {
  59. var eases = {};
  60. var names = ['Quad', 'Cubic', 'Quart', 'Quint', 'Expo'];
  61. var functions = {
  62. Sine: function(t) { return 1 - Math.cos( t * Math.PI / 2 ); },
  63. Circ: function(t) { return 1 - Math.sqrt( 1 - t * t ); },
  64. Elastic: function(t, m) {
  65. if( t === 0 || t === 1 ) return t;
  66. var p = (1 - Math.min(m, 998) / 1000), st = t / 1, st1 = st - 1, s = p / ( 2 * Math.PI ) * Math.asin( 1 );
  67. return -( Math.pow( 2, 10 * st1 ) * Math.sin( ( st1 - s ) * ( 2 * Math.PI ) / p ) );
  68. },
  69. Back: function(t) { return t * t * ( 3 * t - 2 ); },
  70. Bounce: function(t) {
  71. var pow2, bounce = 4;
  72. while ( t < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
  73. return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - t, 2 );
  74. }
  75. }
  76. names.forEach(function(name, i) {
  77. functions[name] = function(t) {
  78. return Math.pow( t, i + 2 );
  79. }
  80. });
  81. Object.keys(functions).forEach(function(name) {
  82. var easeIn = functions[name];
  83. eases['easeIn' + name] = easeIn;
  84. eases['easeOut' + name] = function(t, m) { return 1 - easeIn(1 - t, m); };
  85. eases['easeInOut' + name] = function(t, m) { return t < 0.5 ? easeIn(t * 2, m) / 2 : 1 - easeIn(t * -2 + 2, m) / 2; };
  86. eases['easeOutIn' + name] = function(t, m) { return t < 0.5 ? (1 - easeIn(1 - 2 * t, m)) / 2 : (easeIn(t * 2 - 1, m) + 1) / 2; };
  87. });
  88. eases.linear = function(t) { return t; };
  89. return eases;
  90. })();
  91. // Strings
  92. var numberToString = function(val) {
  93. return (is.str(val)) ? val : val + '';
  94. }
  95. var stringToHyphens = function(str) {
  96. return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  97. }
  98. var selectString = function(str) {
  99. if (is.col(str)) return false;
  100. try {
  101. var nodes = document.querySelectorAll(str);
  102. return nodes;
  103. } catch(e) {
  104. return false;
  105. }
  106. }
  107. // Numbers
  108. var random = function(min, max) {
  109. return Math.floor(Math.random() * (max - min + 1)) + min;
  110. }
  111. // Arrays
  112. var flattenArray = function(arr) {
  113. return arr.reduce(function(a, b) {
  114. return a.concat(is.arr(b) ? flattenArray(b) : b);
  115. }, []);
  116. }
  117. var toArray = function(o) {
  118. if (is.arr(o)) return o;
  119. if (is.str(o)) o = selectString(o) || o;
  120. if (o instanceof NodeList || o instanceof HTMLCollection) return [].slice.call(o);
  121. return [o];
  122. }
  123. var arrayContains = function(arr, val) {
  124. return arr.some(function(a) { return a === val; });
  125. }
  126. var groupArrayByProps = function(arr, propsArr) {
  127. var groups = {};
  128. arr.forEach(function(o) {
  129. var group = JSON.stringify(propsArr.map(function(p) { return o[p]; }));
  130. groups[group] = groups[group] || [];
  131. groups[group].push(o);
  132. });
  133. return Object.keys(groups).map(function(group) {
  134. return groups[group];
  135. });
  136. }
  137. var removeArrayDuplicates = function(arr) {
  138. return arr.filter(function(item, pos, self) {
  139. return self.indexOf(item) === pos;
  140. });
  141. }
  142. // Objects
  143. var cloneObject = function(o) {
  144. var newObject = {};
  145. for (var p in o) newObject[p] = o[p];
  146. return newObject;
  147. }
  148. var mergeObjects = function(o1, o2) {
  149. for (var p in o2) o1[p] = !is.und(o1[p]) ? o1[p] : o2[p];
  150. return o1;
  151. }
  152. // Colors
  153. var hexToRgb = function(hex) {
  154. var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  155. var hex = hex.replace(rgx, function(m, r, g, b) { return r + r + g + g + b + b; });
  156. var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  157. var r = parseInt(rgb[1], 16);
  158. var g = parseInt(rgb[2], 16);
  159. var b = parseInt(rgb[3], 16);
  160. return 'rgb(' + r + ',' + g + ',' + b + ')';
  161. }
  162. var hslToRgb = function(hsl) {
  163. var hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hsl);
  164. var h = parseInt(hsl[1]) / 360;
  165. var s = parseInt(hsl[2]) / 100;
  166. var l = parseInt(hsl[3]) / 100;
  167. var hue2rgb = function(p, q, t) {
  168. if (t < 0) t += 1;
  169. if (t > 1) t -= 1;
  170. if (t < 1/6) return p + (q - p) * 6 * t;
  171. if (t < 1/2) return q;
  172. if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  173. return p;
  174. }
  175. var r, g, b;
  176. if (s == 0) {
  177. r = g = b = l;
  178. } else {
  179. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  180. var p = 2 * l - q;
  181. r = hue2rgb(p, q, h + 1/3);
  182. g = hue2rgb(p, q, h);
  183. b = hue2rgb(p, q, h - 1/3);
  184. }
  185. return 'rgb(' + r * 255 + ',' + g * 255 + ',' + b * 255 + ')';
  186. }
  187. var colorToRgb = function(val) {
  188. if (is.rgb(val)) return val;
  189. if (is.hex(val)) return hexToRgb(val);
  190. if (is.hsl(val)) return hslToRgb(val);
  191. }
  192. // Units
  193. var getUnit = function(val) {
  194. return /([\+\-]?[0-9|auto\.]+)(%|px|pt|em|rem|in|cm|mm|ex|pc|vw|vh|deg)?/.exec(val)[2];
  195. }
  196. var addDefaultTransformUnit = function(prop, val, intialVal) {
  197. if (getUnit(val)) return val;
  198. if (prop.indexOf('translate') > -1) return getUnit(intialVal) ? val + getUnit(intialVal) : val + 'px';
  199. if (prop.indexOf('rotate') > -1 || prop.indexOf('skew') > -1) return val + 'deg';
  200. return val;
  201. }
  202. // Values
  203. var getCSSValue = function(el, prop) {
  204. // First check if prop is a valid CSS property
  205. if (prop in el.style) {
  206. // Then return the property value or fallback to '0' when getPropertyValue fails
  207. return getComputedStyle(el).getPropertyValue(stringToHyphens(prop)) || '0';
  208. }
  209. }
  210. var getTransformValue = function(el, prop) {
  211. var defaultVal = prop.indexOf('scale') > -1 ? 1 : 0;
  212. var str = el.style.transform;
  213. if (!str) return defaultVal;
  214. var rgx = /(\w+)\((.+?)\)/g;
  215. var match = [];
  216. var props = [];
  217. var values = [];
  218. while (match = rgx.exec(str)) {
  219. props.push(match[1]);
  220. values.push(match[2]);
  221. }
  222. var val = values.filter(function(f, i) { return props[i] === prop; });
  223. return val.length ? val[0] : defaultVal;
  224. }
  225. var getAnimationType = function(el, prop) {
  226. if ( is.dom(el) && arrayContains(validTransforms, prop)) return 'transform';
  227. if ( is.dom(el) && (el.getAttribute(prop) || (is.svg(el) && el[prop]))) return 'attribute';
  228. if ( is.dom(el) && (prop !== 'transform' && getCSSValue(el, prop))) return 'css';
  229. if (!is.nul(el[prop]) && !is.und(el[prop])) return 'object';
  230. }
  231. var getInitialTargetValue = function(target, prop) {
  232. switch (getAnimationType(target, prop)) {
  233. case 'transform': return getTransformValue(target, prop);
  234. case 'css': return getCSSValue(target, prop);
  235. case 'attribute': return target.getAttribute(prop);
  236. }
  237. return target[prop] || 0;
  238. }
  239. var getValidValue = function(values, val, originalCSS) {
  240. if (is.col(val)) return colorToRgb(val);
  241. if (getUnit(val)) return val;
  242. var unit = getUnit(values.to) ? getUnit(values.to) : getUnit(values.from);
  243. if (!unit && originalCSS) unit = getUnit(originalCSS);
  244. return unit ? val + unit : val;
  245. }
  246. var decomposeValue = function(val) {
  247. var rgx = /-?\d*\.?\d+/g;
  248. return {
  249. original: val,
  250. numbers: numberToString(val).match(rgx) ? numberToString(val).match(rgx).map(Number) : [0],
  251. strings: numberToString(val).split(rgx)
  252. }
  253. }
  254. var recomposeValue = function(numbers, strings, initialStrings) {
  255. return strings.reduce(function(a, b, i) {
  256. var b = (b ? b : initialStrings[i - 1]);
  257. return a + numbers[i - 1] + b;
  258. });
  259. }
  260. // Animatables
  261. var getAnimatables = function(targets) {
  262. var targets = targets ? (flattenArray(is.arr(targets) ? targets.map(toArray) : toArray(targets))) : [];
  263. return targets.map(function(t, i) {
  264. return { target: t, id: i };
  265. });
  266. }
  267. // Properties
  268. var getProperties = function(params, settings) {
  269. var props = [];
  270. for (var p in params) {
  271. if (!defaultSettings.hasOwnProperty(p) && p !== 'targets') {
  272. var prop = is.obj(params[p]) ? cloneObject(params[p]) : {value: params[p]};
  273. prop.name = p;
  274. props.push(mergeObjects(prop, settings));
  275. }
  276. }
  277. return props;
  278. }
  279. var getPropertiesValues = function(target, prop, value, i) {
  280. var values = toArray( is.fnc(value) ? value(target, i) : value);
  281. return {
  282. from: (values.length > 1) ? values[0] : getInitialTargetValue(target, prop),
  283. to: (values.length > 1) ? values[1] : values[0]
  284. }
  285. }
  286. // Tweens
  287. var getTweenValues = function(prop, values, type, target) {
  288. var valid = {};
  289. if (type === 'transform') {
  290. valid.from = prop + '(' + addDefaultTransformUnit(prop, values.from, values.to) + ')';
  291. valid.to = prop + '(' + addDefaultTransformUnit(prop, values.to) + ')';
  292. } else {
  293. var originalCSS = (type === 'css') ? getCSSValue(target, prop) : undefined;
  294. valid.from = getValidValue(values, values.from, originalCSS);
  295. valid.to = getValidValue(values, values.to, originalCSS);
  296. }
  297. return { from: decomposeValue(valid.from), to: decomposeValue(valid.to) };
  298. }
  299. var getTweensProps = function(animatables, props) {
  300. var tweensProps = [];
  301. animatables.forEach(function(animatable, i) {
  302. var target = animatable.target;
  303. return props.forEach(function(prop) {
  304. var animType = getAnimationType(target, prop.name);
  305. if (animType) {
  306. var values = getPropertiesValues(target, prop.name, prop.value, i);
  307. var tween = cloneObject(prop);
  308. tween.animatables = animatable;
  309. tween.type = animType;
  310. tween.from = getTweenValues(prop.name, values, tween.type, target).from;
  311. tween.to = getTweenValues(prop.name, values, tween.type, target).to;
  312. tween.round = (is.col(values.from) || tween.round) ? 1 : 0;
  313. tween.delay = (is.fnc(tween.delay) ? tween.delay(target, i, animatables.length) : tween.delay) / animation.speed;
  314. tween.duration = (is.fnc(tween.duration) ? tween.duration(target, i, animatables.length) : tween.duration) / animation.speed;
  315. tweensProps.push(tween);
  316. }
  317. });
  318. });
  319. return tweensProps;
  320. }
  321. var getTweens = function(animatables, props) {
  322. var tweensProps = getTweensProps(animatables, props);
  323. var splittedProps = groupArrayByProps(tweensProps, ['name', 'from', 'to', 'delay', 'duration']);
  324. return splittedProps.map(function(tweenProps) {
  325. var tween = cloneObject(tweenProps[0]);
  326. tween.animatables = tweenProps.map(function(p) { return p.animatables });
  327. tween.totalDuration = tween.delay + tween.duration;
  328. return tween;
  329. });
  330. }
  331. var reverseTweens = function(anim, delays) {
  332. anim.tweens.forEach(function(tween) {
  333. var toVal = tween.to;
  334. var fromVal = tween.from;
  335. var delayVal = anim.duration - (tween.delay + tween.duration);
  336. tween.from = toVal;
  337. tween.to = fromVal;
  338. if (delays) tween.delay = delayVal;
  339. });
  340. anim.reversed = anim.reversed ? false : true;
  341. }
  342. var getTweensDuration = function(tweens) {
  343. if (tweens.length) return Math.max.apply(Math, tweens.map(function(tween){ return tween.totalDuration; }));
  344. }
  345. var getTweensDelay = function(tweens) {
  346. if (tweens.length) return Math.min.apply(Math, tweens.map(function(tween){ return tween.delay; }));
  347. }
  348. // will-change
  349. var getWillChange = function(anim) {
  350. var props = [];
  351. var els = [];
  352. anim.tweens.forEach(function(tween) {
  353. if (tween.type === 'css' || tween.type === 'transform' ) {
  354. props.push(tween.type === 'css' ? stringToHyphens(tween.name) : 'transform');
  355. tween.animatables.forEach(function(animatable) { els.push(animatable.target); });
  356. }
  357. });
  358. return {
  359. properties: removeArrayDuplicates(props).join(', '),
  360. elements: removeArrayDuplicates(els)
  361. }
  362. }
  363. var setWillChange = function(anim) {
  364. var willChange = getWillChange(anim);
  365. willChange.elements.forEach(function(element) {
  366. element.style.willChange = willChange.properties;
  367. });
  368. }
  369. var removeWillChange = function(anim) {
  370. var willChange = getWillChange(anim);
  371. willChange.elements.forEach(function(element) {
  372. element.style.removeProperty('will-change');
  373. });
  374. }
  375. /* Svg path */
  376. var getPathProps = function(path) {
  377. var el = is.str(path) ? selectString(path)[0] : path;
  378. return {
  379. path: el,
  380. value: el.getTotalLength()
  381. }
  382. }
  383. var snapProgressToPath = function(tween, progress) {
  384. var pathEl = tween.path;
  385. var pathProgress = tween.value * progress;
  386. var point = function(offset) {
  387. var o = offset || 0;
  388. var p = progress > 1 ? tween.value + o : pathProgress + o;
  389. return pathEl.getPointAtLength(p);
  390. }
  391. var p = point();
  392. var p0 = point(-1);
  393. var p1 = point(+1);
  394. switch (tween.name) {
  395. case 'translateX': return p.x;
  396. case 'translateY': return p.y;
  397. case 'rotate': return Math.atan2(p1.y - p0.y, p1.x - p0.x) * 180 / Math.PI;
  398. }
  399. }
  400. // Progress
  401. var getTweenProgress = function(tween, time) {
  402. var elapsed = Math.min(Math.max(time - tween.delay, 0), tween.duration);
  403. var percent = elapsed / tween.duration;
  404. var progress = tween.to.numbers.map(function(number, p) {
  405. var start = tween.from.numbers[p];
  406. var eased = easings[tween.easing](percent, tween.elasticity);
  407. var val = tween.path ? snapProgressToPath(tween, eased) : start + eased * (number - start);
  408. val = tween.round ? Math.round(val * tween.round) / tween.round : val;
  409. return val;
  410. });
  411. return recomposeValue(progress, tween.to.strings, tween.from.strings);
  412. }
  413. var setAnimationProgress = function(anim, time) {
  414. var transforms;
  415. anim.currentTime = time;
  416. anim.progress = (time / anim.duration) * 100;
  417. for (var t = 0; t < anim.tweens.length; t++) {
  418. var tween = anim.tweens[t];
  419. tween.currentValue = getTweenProgress(tween, time);
  420. var progress = tween.currentValue;
  421. for (var a = 0; a < tween.animatables.length; a++) {
  422. var animatable = tween.animatables[a];
  423. var id = animatable.id;
  424. var target = animatable.target;
  425. var name = tween.name;
  426. switch (tween.type) {
  427. case 'css': target.style[name] = progress; break;
  428. case 'attribute': target.setAttribute(name, progress); break;
  429. case 'object': target[name] = progress; break;
  430. case 'transform':
  431. if (!transforms) transforms = {};
  432. if (!transforms[id]) transforms[id] = [];
  433. transforms[id].push(progress);
  434. break;
  435. }
  436. }
  437. }
  438. if (transforms) {
  439. if (!transform) transform = (getCSSValue(document.body, transformStr) ? '' : '-webkit-') + transformStr;
  440. for (var t in transforms) {
  441. anim.animatables[t].target.style[transform] = transforms[t].join(' ');
  442. }
  443. }
  444. }
  445. // Animation
  446. var createAnimation = function(params) {
  447. var anim = {};
  448. anim.animatables = getAnimatables(params.targets);
  449. anim.settings = mergeObjects(params, defaultSettings);
  450. anim.properties = getProperties(params, anim.settings);
  451. anim.tweens = getTweens(anim.animatables, anim.properties);
  452. anim.duration = getTweensDuration(anim.tweens) || params.duration;
  453. anim.delay = getTweensDelay(anim.tweens) || params.delay;
  454. anim.currentTime = 0;
  455. anim.progress = 0;
  456. anim.ended = false;
  457. return anim;
  458. }
  459. // Public
  460. var animations = [];
  461. var raf = 0;
  462. var engine = (function() {
  463. var play = function() { raf = requestAnimationFrame(step); };
  464. var step = function(t) {
  465. if (animations.length) {
  466. for (var i = 0; i < animations.length; i++) animations[i].tick(t);
  467. play();
  468. } else {
  469. cancelAnimationFrame(raf);
  470. raf = 0;
  471. }
  472. }
  473. return play;
  474. })();
  475. var animation = function(params) {
  476. var anim = createAnimation(params);
  477. var time = {};
  478. anim.tick = function(now) {
  479. anim.ended = false;
  480. if (!time.start) time.start = now;
  481. time.current = Math.min(Math.max(time.last + now - time.start, 0), anim.duration);
  482. setAnimationProgress(anim, time.current);
  483. var s = anim.settings;
  484. if (time.current >= anim.delay) {
  485. if (s.begin) s.begin(anim); s.begin = undefined;
  486. if (s.update) s.update(anim);
  487. }
  488. if (time.current >= anim.duration) {
  489. if (s.loop) {
  490. time.start = now;
  491. if (s.direction === 'alternate') reverseTweens(anim, true);
  492. if (is.num(s.loop)) s.loop--;
  493. } else {
  494. anim.ended = true;
  495. anim.pause();
  496. if (s.complete) s.complete(anim);
  497. }
  498. time.last = 0;
  499. }
  500. }
  501. anim.seek = function(progress) {
  502. setAnimationProgress(anim, (progress / 100) * anim.duration);
  503. }
  504. anim.pause = function() {
  505. removeWillChange(anim);
  506. var i = animations.indexOf(anim);
  507. if (i > -1) animations.splice(i, 1);
  508. }
  509. anim.play = function(params) {
  510. anim.pause();
  511. if (params) anim = mergeObjects(createAnimation(mergeObjects(params, anim.settings)), anim);
  512. time.start = 0;
  513. time.last = anim.ended ? 0 : anim.currentTime;
  514. var s = anim.settings;
  515. if (s.direction === 'reverse') reverseTweens(anim);
  516. if (s.direction === 'alternate' && !s.loop) s.loop = 1;
  517. setWillChange(anim);
  518. animations.push(anim);
  519. if (!raf) engine();
  520. }
  521. anim.restart = function() {
  522. if (anim.reversed) reverseTweens(anim);
  523. anim.pause();
  524. anim.seek(0);
  525. anim.play();
  526. }
  527. if (anim.settings.autoplay) anim.play();
  528. return anim;
  529. }
  530. // Remove one or multiple targets from all active animations.
  531. var remove = function(elements) {
  532. var targets = flattenArray(is.arr(elements) ? elements.map(toArray) : toArray(elements));
  533. for (var i = animations.length-1; i >= 0; i--) {
  534. var animation = animations[i];
  535. var tweens = animation.tweens;
  536. for (var t = tweens.length-1; t >= 0; t--) {
  537. var animatables = tweens[t].animatables;
  538. for (var a = animatables.length-1; a >= 0; a--) {
  539. if (arrayContains(targets, animatables[a].target)) {
  540. animatables.splice(a, 1);
  541. if (!animatables.length) tweens.splice(t, 1);
  542. if (!tweens.length) animation.pause();
  543. }
  544. }
  545. }
  546. }
  547. }
  548. animation.version = version;
  549. animation.speed = 1;
  550. animation.list = animations;
  551. animation.remove = remove;
  552. animation.easings = easings;
  553. animation.getValue = getInitialTargetValue;
  554. animation.path = getPathProps;
  555. animation.random = random;
  556. return animation;
  557. }));