Animator.js 24 KB

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