Animator.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. import Clip from './Clip.js';
  2. import * as color from '../tool/color.js';
  3. import { eqNaN, extend, isArrayLike, isFunction, isGradientObject, isNumber, isString, keys, logError, map } from '../core/util.js';
  4. import easingFuncs from './easing.js';
  5. import { createCubicEasingFunc } from './cubicEasing.js';
  6. import { isLinearGradient, isRadialGradient } from '../svg/helper.js';
  7. ;
  8. var arraySlice = Array.prototype.slice;
  9. function interpolateNumber(p0, p1, percent) {
  10. return (p1 - p0) * percent + p0;
  11. }
  12. function interpolate1DArray(out, p0, p1, percent) {
  13. var len = p0.length;
  14. for (var i = 0; i < len; i++) {
  15. out[i] = interpolateNumber(p0[i], p1[i], percent);
  16. }
  17. return out;
  18. }
  19. function interpolate2DArray(out, p0, p1, percent) {
  20. var len = p0.length;
  21. var len2 = len && p0[0].length;
  22. for (var i = 0; i < len; i++) {
  23. if (!out[i]) {
  24. out[i] = [];
  25. }
  26. for (var j = 0; j < len2; j++) {
  27. out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
  28. }
  29. }
  30. return out;
  31. }
  32. function add1DArray(out, p0, p1, sign) {
  33. var len = p0.length;
  34. for (var i = 0; i < len; i++) {
  35. out[i] = p0[i] + p1[i] * sign;
  36. }
  37. return out;
  38. }
  39. function add2DArray(out, p0, p1, sign) {
  40. var len = p0.length;
  41. var len2 = len && p0[0].length;
  42. for (var i = 0; i < len; i++) {
  43. if (!out[i]) {
  44. out[i] = [];
  45. }
  46. for (var j = 0; j < len2; j++) {
  47. out[i][j] = p0[i][j] + p1[i][j] * sign;
  48. }
  49. }
  50. return out;
  51. }
  52. function fillColorStops(val0, val1) {
  53. var len0 = val0.length;
  54. var len1 = val1.length;
  55. var shorterArr = len0 > len1 ? val1 : val0;
  56. var shorterLen = Math.min(len0, len1);
  57. var last = shorterArr[shorterLen - 1] || { color: [0, 0, 0, 0], offset: 0 };
  58. for (var i = shorterLen; i < Math.max(len0, len1); i++) {
  59. shorterArr.push({
  60. offset: last.offset,
  61. color: last.color.slice()
  62. });
  63. }
  64. }
  65. function fillArray(val0, val1, arrDim) {
  66. var arr0 = val0;
  67. var arr1 = val1;
  68. if (!arr0.push || !arr1.push) {
  69. return;
  70. }
  71. var arr0Len = arr0.length;
  72. var arr1Len = arr1.length;
  73. if (arr0Len !== arr1Len) {
  74. var isPreviousLarger = arr0Len > arr1Len;
  75. if (isPreviousLarger) {
  76. arr0.length = arr1Len;
  77. }
  78. else {
  79. for (var i = arr0Len; i < arr1Len; i++) {
  80. arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
  81. }
  82. }
  83. }
  84. var len2 = arr0[0] && arr0[0].length;
  85. for (var i = 0; i < arr0.length; i++) {
  86. if (arrDim === 1) {
  87. if (isNaN(arr0[i])) {
  88. arr0[i] = arr1[i];
  89. }
  90. }
  91. else {
  92. for (var j = 0; j < len2; j++) {
  93. if (isNaN(arr0[i][j])) {
  94. arr0[i][j] = arr1[i][j];
  95. }
  96. }
  97. }
  98. }
  99. }
  100. export function cloneValue(value) {
  101. if (isArrayLike(value)) {
  102. var len = value.length;
  103. if (isArrayLike(value[0])) {
  104. var ret = [];
  105. for (var i = 0; i < len; i++) {
  106. ret.push(arraySlice.call(value[i]));
  107. }
  108. return ret;
  109. }
  110. return arraySlice.call(value);
  111. }
  112. return value;
  113. }
  114. function rgba2String(rgba) {
  115. rgba[0] = Math.floor(rgba[0]) || 0;
  116. rgba[1] = Math.floor(rgba[1]) || 0;
  117. rgba[2] = Math.floor(rgba[2]) || 0;
  118. rgba[3] = rgba[3] == null ? 1 : rgba[3];
  119. return 'rgba(' + rgba.join(',') + ')';
  120. }
  121. function guessArrayDim(value) {
  122. return isArrayLike(value && value[0]) ? 2 : 1;
  123. }
  124. var VALUE_TYPE_NUMBER = 0;
  125. var VALUE_TYPE_1D_ARRAY = 1;
  126. var VALUE_TYPE_2D_ARRAY = 2;
  127. var VALUE_TYPE_COLOR = 3;
  128. var VALUE_TYPE_LINEAR_GRADIENT = 4;
  129. var VALUE_TYPE_RADIAL_GRADIENT = 5;
  130. var VALUE_TYPE_UNKOWN = 6;
  131. function isGradientValueType(valType) {
  132. return valType === VALUE_TYPE_LINEAR_GRADIENT || valType === VALUE_TYPE_RADIAL_GRADIENT;
  133. }
  134. function isArrayValueType(valType) {
  135. return valType === VALUE_TYPE_1D_ARRAY || valType === VALUE_TYPE_2D_ARRAY;
  136. }
  137. var tmpRgba = [0, 0, 0, 0];
  138. var Track = (function () {
  139. function Track(propName) {
  140. this.keyframes = [];
  141. this.discrete = false;
  142. this._invalid = false;
  143. this._needsSort = false;
  144. this._lastFr = 0;
  145. this._lastFrP = 0;
  146. this.propName = propName;
  147. }
  148. Track.prototype.isFinished = function () {
  149. return this._finished;
  150. };
  151. Track.prototype.setFinished = function () {
  152. this._finished = true;
  153. if (this._additiveTrack) {
  154. this._additiveTrack.setFinished();
  155. }
  156. };
  157. Track.prototype.needsAnimate = function () {
  158. return this.keyframes.length >= 1;
  159. };
  160. Track.prototype.getAdditiveTrack = function () {
  161. return this._additiveTrack;
  162. };
  163. Track.prototype.addKeyframe = function (time, rawValue, easing) {
  164. this._needsSort = true;
  165. var keyframes = this.keyframes;
  166. var len = keyframes.length;
  167. var discrete = false;
  168. var valType = VALUE_TYPE_UNKOWN;
  169. var value = rawValue;
  170. if (isArrayLike(rawValue)) {
  171. var arrayDim = guessArrayDim(rawValue);
  172. valType = arrayDim;
  173. if (arrayDim === 1 && !isNumber(rawValue[0])
  174. || arrayDim === 2 && !isNumber(rawValue[0][0])) {
  175. discrete = true;
  176. }
  177. }
  178. else {
  179. if (isNumber(rawValue) && !eqNaN(rawValue)) {
  180. valType = VALUE_TYPE_NUMBER;
  181. }
  182. else if (isString(rawValue)) {
  183. if (!isNaN(+rawValue)) {
  184. valType = VALUE_TYPE_NUMBER;
  185. }
  186. else {
  187. var colorArray = color.parse(rawValue);
  188. if (colorArray) {
  189. value = colorArray;
  190. valType = VALUE_TYPE_COLOR;
  191. }
  192. }
  193. }
  194. else if (isGradientObject(rawValue)) {
  195. var parsedGradient = extend({}, value);
  196. parsedGradient.colorStops = map(rawValue.colorStops, function (colorStop) { return ({
  197. offset: colorStop.offset,
  198. color: color.parse(colorStop.color)
  199. }); });
  200. if (isLinearGradient(rawValue)) {
  201. valType = VALUE_TYPE_LINEAR_GRADIENT;
  202. }
  203. else if (isRadialGradient(rawValue)) {
  204. valType = VALUE_TYPE_RADIAL_GRADIENT;
  205. }
  206. value = parsedGradient;
  207. }
  208. }
  209. if (len === 0) {
  210. this.valType = valType;
  211. }
  212. else if (valType !== this.valType || valType === VALUE_TYPE_UNKOWN) {
  213. discrete = true;
  214. }
  215. this.discrete = this.discrete || discrete;
  216. var kf = {
  217. time: time,
  218. value: value,
  219. rawValue: rawValue,
  220. percent: 0
  221. };
  222. if (easing) {
  223. kf.easing = easing;
  224. kf.easingFunc = isFunction(easing)
  225. ? easing
  226. : easingFuncs[easing] || createCubicEasingFunc(easing);
  227. }
  228. keyframes.push(kf);
  229. return kf;
  230. };
  231. Track.prototype.prepare = function (maxTime, additiveTrack) {
  232. var kfs = this.keyframes;
  233. if (this._needsSort) {
  234. kfs.sort(function (a, b) {
  235. return a.time - b.time;
  236. });
  237. }
  238. var valType = this.valType;
  239. var kfsLen = kfs.length;
  240. var lastKf = kfs[kfsLen - 1];
  241. var isDiscrete = this.discrete;
  242. var isArr = isArrayValueType(valType);
  243. var isGradient = isGradientValueType(valType);
  244. for (var i = 0; i < kfsLen; i++) {
  245. var kf = kfs[i];
  246. var value = kf.value;
  247. var lastValue = lastKf.value;
  248. kf.percent = kf.time / maxTime;
  249. if (!isDiscrete) {
  250. if (isArr && i !== kfsLen - 1) {
  251. fillArray(value, lastValue, valType);
  252. }
  253. else if (isGradient) {
  254. fillColorStops(value.colorStops, lastValue.colorStops);
  255. }
  256. }
  257. }
  258. if (!isDiscrete
  259. && valType !== VALUE_TYPE_RADIAL_GRADIENT
  260. && additiveTrack
  261. && this.needsAnimate()
  262. && additiveTrack.needsAnimate()
  263. && valType === additiveTrack.valType
  264. && !additiveTrack._finished) {
  265. this._additiveTrack = additiveTrack;
  266. var startValue = kfs[0].value;
  267. for (var i = 0; i < kfsLen; i++) {
  268. if (valType === VALUE_TYPE_NUMBER) {
  269. kfs[i].additiveValue = kfs[i].value - startValue;
  270. }
  271. else if (valType === VALUE_TYPE_COLOR) {
  272. kfs[i].additiveValue =
  273. add1DArray([], kfs[i].value, startValue, -1);
  274. }
  275. else if (isArrayValueType(valType)) {
  276. kfs[i].additiveValue = valType === VALUE_TYPE_1D_ARRAY
  277. ? add1DArray([], kfs[i].value, startValue, -1)
  278. : add2DArray([], kfs[i].value, startValue, -1);
  279. }
  280. }
  281. }
  282. };
  283. Track.prototype.step = function (target, percent) {
  284. if (this._finished) {
  285. return;
  286. }
  287. if (this._additiveTrack && this._additiveTrack._finished) {
  288. this._additiveTrack = null;
  289. }
  290. var isAdditive = this._additiveTrack != null;
  291. var valueKey = isAdditive ? 'additiveValue' : 'value';
  292. var valType = this.valType;
  293. var keyframes = this.keyframes;
  294. var kfsNum = keyframes.length;
  295. var propName = this.propName;
  296. var isValueColor = valType === VALUE_TYPE_COLOR;
  297. var frameIdx;
  298. var lastFrame = this._lastFr;
  299. var mathMin = Math.min;
  300. var frame;
  301. var nextFrame;
  302. if (kfsNum === 1) {
  303. frame = nextFrame = keyframes[0];
  304. }
  305. else {
  306. if (percent < 0) {
  307. frameIdx = 0;
  308. }
  309. else if (percent < this._lastFrP) {
  310. var start = mathMin(lastFrame + 1, kfsNum - 1);
  311. for (frameIdx = start; frameIdx >= 0; frameIdx--) {
  312. if (keyframes[frameIdx].percent <= percent) {
  313. break;
  314. }
  315. }
  316. frameIdx = mathMin(frameIdx, kfsNum - 2);
  317. }
  318. else {
  319. for (frameIdx = lastFrame; frameIdx < kfsNum; frameIdx++) {
  320. if (keyframes[frameIdx].percent > percent) {
  321. break;
  322. }
  323. }
  324. frameIdx = mathMin(frameIdx - 1, kfsNum - 2);
  325. }
  326. nextFrame = keyframes[frameIdx + 1];
  327. frame = keyframes[frameIdx];
  328. }
  329. if (!(frame && nextFrame)) {
  330. return;
  331. }
  332. this._lastFr = frameIdx;
  333. this._lastFrP = percent;
  334. var interval = (nextFrame.percent - frame.percent);
  335. var w = interval === 0 ? 1 : mathMin((percent - frame.percent) / interval, 1);
  336. if (nextFrame.easingFunc) {
  337. w = nextFrame.easingFunc(w);
  338. }
  339. var targetArr = isAdditive ? this._additiveValue
  340. : (isValueColor ? tmpRgba : target[propName]);
  341. if ((isArrayValueType(valType) || isValueColor) && !targetArr) {
  342. targetArr = this._additiveValue = [];
  343. }
  344. if (this.discrete) {
  345. target[propName] = w < 1 ? frame.rawValue : nextFrame.rawValue;
  346. }
  347. else if (isArrayValueType(valType)) {
  348. valType === VALUE_TYPE_1D_ARRAY
  349. ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w)
  350. : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
  351. }
  352. else if (isGradientValueType(valType)) {
  353. var val = frame[valueKey];
  354. var nextVal_1 = nextFrame[valueKey];
  355. var isLinearGradient_1 = valType === VALUE_TYPE_LINEAR_GRADIENT;
  356. target[propName] = {
  357. type: isLinearGradient_1 ? 'linear' : 'radial',
  358. x: interpolateNumber(val.x, nextVal_1.x, w),
  359. y: interpolateNumber(val.y, nextVal_1.y, w),
  360. colorStops: map(val.colorStops, function (colorStop, idx) {
  361. var nextColorStop = nextVal_1.colorStops[idx];
  362. return {
  363. offset: interpolateNumber(colorStop.offset, nextColorStop.offset, w),
  364. color: rgba2String(interpolate1DArray([], colorStop.color, nextColorStop.color, w))
  365. };
  366. }),
  367. global: nextVal_1.global
  368. };
  369. if (isLinearGradient_1) {
  370. target[propName].x2 = interpolateNumber(val.x2, nextVal_1.x2, w);
  371. target[propName].y2 = interpolateNumber(val.y2, nextVal_1.y2, w);
  372. }
  373. else {
  374. target[propName].r = interpolateNumber(val.r, nextVal_1.r, w);
  375. }
  376. }
  377. else if (isValueColor) {
  378. interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
  379. if (!isAdditive) {
  380. target[propName] = rgba2String(targetArr);
  381. }
  382. }
  383. else {
  384. var value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w);
  385. if (isAdditive) {
  386. this._additiveValue = value;
  387. }
  388. else {
  389. target[propName] = value;
  390. }
  391. }
  392. if (isAdditive) {
  393. this._addToTarget(target);
  394. }
  395. };
  396. Track.prototype._addToTarget = function (target) {
  397. var valType = this.valType;
  398. var propName = this.propName;
  399. var additiveValue = this._additiveValue;
  400. if (valType === VALUE_TYPE_NUMBER) {
  401. target[propName] = target[propName] + additiveValue;
  402. }
  403. else if (valType === VALUE_TYPE_COLOR) {
  404. color.parse(target[propName], tmpRgba);
  405. add1DArray(tmpRgba, tmpRgba, additiveValue, 1);
  406. target[propName] = rgba2String(tmpRgba);
  407. }
  408. else if (valType === VALUE_TYPE_1D_ARRAY) {
  409. add1DArray(target[propName], target[propName], additiveValue, 1);
  410. }
  411. else if (valType === VALUE_TYPE_2D_ARRAY) {
  412. add2DArray(target[propName], target[propName], additiveValue, 1);
  413. }
  414. };
  415. return Track;
  416. }());
  417. var Animator = (function () {
  418. function Animator(target, loop, allowDiscreteAnimation, additiveTo) {
  419. this._tracks = {};
  420. this._trackKeys = [];
  421. this._maxTime = 0;
  422. this._started = 0;
  423. this._clip = null;
  424. this._target = target;
  425. this._loop = loop;
  426. if (loop && additiveTo) {
  427. logError('Can\' use additive animation on looped animation.');
  428. return;
  429. }
  430. this._additiveAnimators = additiveTo;
  431. this._allowDiscrete = allowDiscreteAnimation;
  432. }
  433. Animator.prototype.getMaxTime = function () {
  434. return this._maxTime;
  435. };
  436. Animator.prototype.getDelay = function () {
  437. return this._delay;
  438. };
  439. Animator.prototype.getLoop = function () {
  440. return this._loop;
  441. };
  442. Animator.prototype.getTarget = function () {
  443. return this._target;
  444. };
  445. Animator.prototype.changeTarget = function (target) {
  446. this._target = target;
  447. };
  448. Animator.prototype.when = function (time, props, easing) {
  449. return this.whenWithKeys(time, props, keys(props), easing);
  450. };
  451. Animator.prototype.whenWithKeys = function (time, props, propNames, easing) {
  452. var tracks = this._tracks;
  453. for (var i = 0; i < propNames.length; i++) {
  454. var propName = propNames[i];
  455. var track = tracks[propName];
  456. if (!track) {
  457. track = tracks[propName] = new Track(propName);
  458. var initialValue = void 0;
  459. var additiveTrack = this._getAdditiveTrack(propName);
  460. if (additiveTrack) {
  461. var addtiveTrackKfs = additiveTrack.keyframes;
  462. var lastFinalKf = addtiveTrackKfs[addtiveTrackKfs.length - 1];
  463. initialValue = lastFinalKf && lastFinalKf.value;
  464. if (additiveTrack.valType === VALUE_TYPE_COLOR && initialValue) {
  465. initialValue = rgba2String(initialValue);
  466. }
  467. }
  468. else {
  469. initialValue = this._target[propName];
  470. }
  471. if (initialValue == null) {
  472. continue;
  473. }
  474. if (time > 0) {
  475. track.addKeyframe(0, cloneValue(initialValue), easing);
  476. }
  477. this._trackKeys.push(propName);
  478. }
  479. track.addKeyframe(time, cloneValue(props[propName]), easing);
  480. }
  481. this._maxTime = Math.max(this._maxTime, time);
  482. return this;
  483. };
  484. Animator.prototype.pause = function () {
  485. this._clip.pause();
  486. this._paused = true;
  487. };
  488. Animator.prototype.resume = function () {
  489. this._clip.resume();
  490. this._paused = false;
  491. };
  492. Animator.prototype.isPaused = function () {
  493. return !!this._paused;
  494. };
  495. Animator.prototype.duration = function (duration) {
  496. this._maxTime = duration;
  497. this._force = true;
  498. return this;
  499. };
  500. Animator.prototype._doneCallback = function () {
  501. this._setTracksFinished();
  502. this._clip = null;
  503. var doneList = this._doneCbs;
  504. if (doneList) {
  505. var len = doneList.length;
  506. for (var i = 0; i < len; i++) {
  507. doneList[i].call(this);
  508. }
  509. }
  510. };
  511. Animator.prototype._abortedCallback = function () {
  512. this._setTracksFinished();
  513. var animation = this.animation;
  514. var abortedList = this._abortedCbs;
  515. if (animation) {
  516. animation.removeClip(this._clip);
  517. }
  518. this._clip = null;
  519. if (abortedList) {
  520. for (var i = 0; i < abortedList.length; i++) {
  521. abortedList[i].call(this);
  522. }
  523. }
  524. };
  525. Animator.prototype._setTracksFinished = function () {
  526. var tracks = this._tracks;
  527. var tracksKeys = this._trackKeys;
  528. for (var i = 0; i < tracksKeys.length; i++) {
  529. tracks[tracksKeys[i]].setFinished();
  530. }
  531. };
  532. Animator.prototype._getAdditiveTrack = function (trackName) {
  533. var additiveTrack;
  534. var additiveAnimators = this._additiveAnimators;
  535. if (additiveAnimators) {
  536. for (var i = 0; i < additiveAnimators.length; i++) {
  537. var track = additiveAnimators[i].getTrack(trackName);
  538. if (track) {
  539. additiveTrack = track;
  540. }
  541. }
  542. }
  543. return additiveTrack;
  544. };
  545. Animator.prototype.start = function (easing) {
  546. if (this._started > 0) {
  547. return;
  548. }
  549. this._started = 1;
  550. var self = this;
  551. var tracks = [];
  552. var maxTime = this._maxTime || 0;
  553. for (var i = 0; i < this._trackKeys.length; i++) {
  554. var propName = this._trackKeys[i];
  555. var track = this._tracks[propName];
  556. var additiveTrack = this._getAdditiveTrack(propName);
  557. var kfs = track.keyframes;
  558. var kfsNum = kfs.length;
  559. track.prepare(maxTime, additiveTrack);
  560. if (track.needsAnimate()) {
  561. if (!this._allowDiscrete && track.discrete) {
  562. var lastKf = kfs[kfsNum - 1];
  563. if (lastKf) {
  564. self._target[track.propName] = lastKf.rawValue;
  565. }
  566. track.setFinished();
  567. }
  568. else {
  569. tracks.push(track);
  570. }
  571. }
  572. }
  573. if (tracks.length || this._force) {
  574. var clip = new Clip({
  575. life: maxTime,
  576. loop: this._loop,
  577. delay: this._delay || 0,
  578. onframe: function (percent) {
  579. self._started = 2;
  580. var additiveAnimators = self._additiveAnimators;
  581. if (additiveAnimators) {
  582. var stillHasAdditiveAnimator = false;
  583. for (var i = 0; i < additiveAnimators.length; i++) {
  584. if (additiveAnimators[i]._clip) {
  585. stillHasAdditiveAnimator = true;
  586. break;
  587. }
  588. }
  589. if (!stillHasAdditiveAnimator) {
  590. self._additiveAnimators = null;
  591. }
  592. }
  593. for (var i = 0; i < tracks.length; i++) {
  594. tracks[i].step(self._target, percent);
  595. }
  596. var onframeList = self._onframeCbs;
  597. if (onframeList) {
  598. for (var i = 0; i < onframeList.length; i++) {
  599. onframeList[i](self._target, percent);
  600. }
  601. }
  602. },
  603. ondestroy: function () {
  604. self._doneCallback();
  605. }
  606. });
  607. this._clip = clip;
  608. if (this.animation) {
  609. this.animation.addClip(clip);
  610. }
  611. if (easing) {
  612. clip.setEasing(easing);
  613. }
  614. }
  615. else {
  616. this._doneCallback();
  617. }
  618. return this;
  619. };
  620. Animator.prototype.stop = function (forwardToLast) {
  621. if (!this._clip) {
  622. return;
  623. }
  624. var clip = this._clip;
  625. if (forwardToLast) {
  626. clip.onframe(1);
  627. }
  628. this._abortedCallback();
  629. };
  630. Animator.prototype.delay = function (time) {
  631. this._delay = time;
  632. return this;
  633. };
  634. Animator.prototype.during = function (cb) {
  635. if (cb) {
  636. if (!this._onframeCbs) {
  637. this._onframeCbs = [];
  638. }
  639. this._onframeCbs.push(cb);
  640. }
  641. return this;
  642. };
  643. Animator.prototype.done = function (cb) {
  644. if (cb) {
  645. if (!this._doneCbs) {
  646. this._doneCbs = [];
  647. }
  648. this._doneCbs.push(cb);
  649. }
  650. return this;
  651. };
  652. Animator.prototype.aborted = function (cb) {
  653. if (cb) {
  654. if (!this._abortedCbs) {
  655. this._abortedCbs = [];
  656. }
  657. this._abortedCbs.push(cb);
  658. }
  659. return this;
  660. };
  661. Animator.prototype.getClip = function () {
  662. return this._clip;
  663. };
  664. Animator.prototype.getTrack = function (propName) {
  665. return this._tracks[propName];
  666. };
  667. Animator.prototype.getTracks = function () {
  668. var _this = this;
  669. return map(this._trackKeys, function (key) { return _this._tracks[key]; });
  670. };
  671. Animator.prototype.stopTracks = function (propNames, forwardToLast) {
  672. if (!propNames.length || !this._clip) {
  673. return true;
  674. }
  675. var tracks = this._tracks;
  676. var tracksKeys = this._trackKeys;
  677. for (var i = 0; i < propNames.length; i++) {
  678. var track = tracks[propNames[i]];
  679. if (track && !track.isFinished()) {
  680. if (forwardToLast) {
  681. track.step(this._target, 1);
  682. }
  683. else if (this._started === 1) {
  684. track.step(this._target, 0);
  685. }
  686. track.setFinished();
  687. }
  688. }
  689. var allAborted = true;
  690. for (var i = 0; i < tracksKeys.length; i++) {
  691. if (!tracks[tracksKeys[i]].isFinished()) {
  692. allAborted = false;
  693. break;
  694. }
  695. }
  696. if (allAborted) {
  697. this._abortedCallback();
  698. }
  699. return allAborted;
  700. };
  701. Animator.prototype.saveTo = function (target, trackKeys, firstOrLast) {
  702. if (!target) {
  703. return;
  704. }
  705. trackKeys = trackKeys || this._trackKeys;
  706. for (var i = 0; i < trackKeys.length; i++) {
  707. var propName = trackKeys[i];
  708. var track = this._tracks[propName];
  709. if (!track || track.isFinished()) {
  710. continue;
  711. }
  712. var kfs = track.keyframes;
  713. var kf = kfs[firstOrLast ? 0 : kfs.length - 1];
  714. if (kf) {
  715. target[propName] = cloneValue(kf.rawValue);
  716. }
  717. }
  718. };
  719. Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) {
  720. trackKeys = trackKeys || keys(finalProps);
  721. for (var i = 0; i < trackKeys.length; i++) {
  722. var propName = trackKeys[i];
  723. var track = this._tracks[propName];
  724. if (!track) {
  725. continue;
  726. }
  727. var kfs = track.keyframes;
  728. if (kfs.length > 1) {
  729. var lastKf = kfs.pop();
  730. track.addKeyframe(lastKf.time, finalProps[propName]);
  731. track.prepare(this._maxTime, track.getAdditiveTrack());
  732. }
  733. }
  734. };
  735. return Animator;
  736. }());
  737. export default Animator;