AnimationItem.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. import {
  2. extendPrototype,
  3. } from '../utils/functionExtensions';
  4. import audioControllerFactory from '../utils/audio/AudioController';
  5. import {
  6. getSubframeEnabled,
  7. BMEnterFrameEvent,
  8. BMCompleteEvent,
  9. BMCompleteLoopEvent,
  10. BMSegmentStartEvent,
  11. BMDestroyEvent,
  12. BMRenderFrameErrorEvent,
  13. BMConfigErrorEvent,
  14. createElementID,
  15. getExpressionsPlugin,
  16. } from '../utils/common';
  17. import ImagePreloader from '../utils/imagePreloader';
  18. import BaseEvent from '../utils/BaseEvent';
  19. import dataManager from '../utils/DataManager';
  20. import markerParser from '../utils/markers/markerParser';
  21. import ProjectInterface from '../utils/expressions/ProjectInterface';
  22. import { getRenderer, getRegisteredRenderer } from '../renderers/renderersManager';
  23. const AnimationItem = function () {
  24. this._cbs = [];
  25. this.name = '';
  26. this.path = '';
  27. this.isLoaded = false;
  28. this.currentFrame = 0;
  29. this.currentRawFrame = 0;
  30. this.firstFrame = 0;
  31. this.totalFrames = 0;
  32. this.frameRate = 0;
  33. this.frameMult = 0;
  34. this.playSpeed = 1;
  35. this.playDirection = 1;
  36. this.playCount = 0;
  37. this.animationData = {};
  38. this.assets = [];
  39. this.isPaused = true;
  40. this.autoplay = false;
  41. this.loop = true;
  42. this.renderer = null;
  43. this.animationID = createElementID();
  44. this.assetsPath = '';
  45. this.timeCompleted = 0;
  46. this.segmentPos = 0;
  47. this.isSubframeEnabled = getSubframeEnabled();
  48. this.segments = [];
  49. this._idle = true;
  50. this._completedLoop = false;
  51. this.projectInterface = ProjectInterface();
  52. this.imagePreloader = new ImagePreloader();
  53. this.audioController = audioControllerFactory();
  54. this.markers = [];
  55. this.configAnimation = this.configAnimation.bind(this);
  56. this.onSetupError = this.onSetupError.bind(this);
  57. this.onSegmentComplete = this.onSegmentComplete.bind(this);
  58. this.drawnFrameEvent = new BMEnterFrameEvent('drawnFrame', 0, 0, 0);
  59. this.expressionsPlugin = getExpressionsPlugin();
  60. };
  61. extendPrototype([BaseEvent], AnimationItem);
  62. AnimationItem.prototype.setParams = function (params) {
  63. if (params.wrapper || params.container) {
  64. this.wrapper = params.wrapper || params.container;
  65. }
  66. var animType = 'svg';
  67. if (params.animType) {
  68. animType = params.animType;
  69. } else if (params.renderer) {
  70. animType = params.renderer;
  71. }
  72. const RendererClass = getRenderer(animType);
  73. this.renderer = new RendererClass(this, params.rendererSettings);
  74. this.imagePreloader.setCacheType(animType, this.renderer.globalData.defs);
  75. this.renderer.setProjectInterface(this.projectInterface);
  76. this.animType = animType;
  77. if (params.loop === ''
  78. || params.loop === null
  79. || params.loop === undefined
  80. || params.loop === true) {
  81. this.loop = true;
  82. } else if (params.loop === false) {
  83. this.loop = false;
  84. } else {
  85. this.loop = parseInt(params.loop, 10);
  86. }
  87. this.autoplay = 'autoplay' in params ? params.autoplay : true;
  88. this.name = params.name ? params.name : '';
  89. this.autoloadSegments = Object.prototype.hasOwnProperty.call(params, 'autoloadSegments') ? params.autoloadSegments : true;
  90. this.assetsPath = params.assetsPath;
  91. this.initialSegment = params.initialSegment;
  92. if (params.audioFactory) {
  93. this.audioController.setAudioFactory(params.audioFactory);
  94. }
  95. if (params.animationData) {
  96. this.setupAnimation(params.animationData);
  97. } else if (params.path) {
  98. if (params.path.lastIndexOf('\\') !== -1) {
  99. this.path = params.path.substr(0, params.path.lastIndexOf('\\') + 1);
  100. } else {
  101. this.path = params.path.substr(0, params.path.lastIndexOf('/') + 1);
  102. }
  103. this.fileName = params.path.substr(params.path.lastIndexOf('/') + 1);
  104. this.fileName = this.fileName.substr(0, this.fileName.lastIndexOf('.json'));
  105. dataManager.loadAnimation(
  106. params.path,
  107. this.configAnimation,
  108. this.onSetupError
  109. );
  110. }
  111. };
  112. AnimationItem.prototype.onSetupError = function () {
  113. this.trigger('data_failed');
  114. };
  115. AnimationItem.prototype.setupAnimation = function (data) {
  116. dataManager.completeAnimation(
  117. data,
  118. this.configAnimation
  119. );
  120. };
  121. AnimationItem.prototype.setData = function (wrapper, animationData) {
  122. if (animationData) {
  123. if (typeof animationData !== 'object') {
  124. animationData = JSON.parse(animationData);
  125. }
  126. }
  127. var params = {
  128. wrapper: wrapper,
  129. animationData: animationData,
  130. };
  131. var wrapperAttributes = wrapper.attributes;
  132. params.path = wrapperAttributes.getNamedItem('data-animation-path') // eslint-disable-line no-nested-ternary
  133. ? wrapperAttributes.getNamedItem('data-animation-path').value
  134. : wrapperAttributes.getNamedItem('data-bm-path') // eslint-disable-line no-nested-ternary
  135. ? wrapperAttributes.getNamedItem('data-bm-path').value
  136. : wrapperAttributes.getNamedItem('bm-path')
  137. ? wrapperAttributes.getNamedItem('bm-path').value
  138. : '';
  139. params.animType = wrapperAttributes.getNamedItem('data-anim-type') // eslint-disable-line no-nested-ternary
  140. ? wrapperAttributes.getNamedItem('data-anim-type').value
  141. : wrapperAttributes.getNamedItem('data-bm-type') // eslint-disable-line no-nested-ternary
  142. ? wrapperAttributes.getNamedItem('data-bm-type').value
  143. : wrapperAttributes.getNamedItem('bm-type') // eslint-disable-line no-nested-ternary
  144. ? wrapperAttributes.getNamedItem('bm-type').value
  145. : wrapperAttributes.getNamedItem('data-bm-renderer') // eslint-disable-line no-nested-ternary
  146. ? wrapperAttributes.getNamedItem('data-bm-renderer').value
  147. : wrapperAttributes.getNamedItem('bm-renderer')
  148. ? wrapperAttributes.getNamedItem('bm-renderer').value
  149. : getRegisteredRenderer() || 'canvas';
  150. var loop = wrapperAttributes.getNamedItem('data-anim-loop') // eslint-disable-line no-nested-ternary
  151. ? wrapperAttributes.getNamedItem('data-anim-loop').value
  152. : wrapperAttributes.getNamedItem('data-bm-loop') // eslint-disable-line no-nested-ternary
  153. ? wrapperAttributes.getNamedItem('data-bm-loop').value
  154. : wrapperAttributes.getNamedItem('bm-loop')
  155. ? wrapperAttributes.getNamedItem('bm-loop').value
  156. : '';
  157. if (loop === 'false') {
  158. params.loop = false;
  159. } else if (loop === 'true') {
  160. params.loop = true;
  161. } else if (loop !== '') {
  162. params.loop = parseInt(loop, 10);
  163. }
  164. var autoplay = wrapperAttributes.getNamedItem('data-anim-autoplay') // eslint-disable-line no-nested-ternary
  165. ? wrapperAttributes.getNamedItem('data-anim-autoplay').value
  166. : wrapperAttributes.getNamedItem('data-bm-autoplay') // eslint-disable-line no-nested-ternary
  167. ? wrapperAttributes.getNamedItem('data-bm-autoplay').value
  168. : wrapperAttributes.getNamedItem('bm-autoplay')
  169. ? wrapperAttributes.getNamedItem('bm-autoplay').value
  170. : true;
  171. params.autoplay = autoplay !== 'false';
  172. params.name = wrapperAttributes.getNamedItem('data-name') // eslint-disable-line no-nested-ternary
  173. ? wrapperAttributes.getNamedItem('data-name').value
  174. : wrapperAttributes.getNamedItem('data-bm-name') // eslint-disable-line no-nested-ternary
  175. ? wrapperAttributes.getNamedItem('data-bm-name').value
  176. : wrapperAttributes.getNamedItem('bm-name')
  177. ? wrapperAttributes.getNamedItem('bm-name').value
  178. : '';
  179. var prerender = wrapperAttributes.getNamedItem('data-anim-prerender') // eslint-disable-line no-nested-ternary
  180. ? wrapperAttributes.getNamedItem('data-anim-prerender').value
  181. : wrapperAttributes.getNamedItem('data-bm-prerender') // eslint-disable-line no-nested-ternary
  182. ? wrapperAttributes.getNamedItem('data-bm-prerender').value
  183. : wrapperAttributes.getNamedItem('bm-prerender')
  184. ? wrapperAttributes.getNamedItem('bm-prerender').value
  185. : '';
  186. if (prerender === 'false') {
  187. params.prerender = false;
  188. }
  189. if (!params.path) {
  190. this.trigger('destroy');
  191. } else {
  192. this.setParams(params);
  193. }
  194. };
  195. AnimationItem.prototype.includeLayers = function (data) {
  196. if (data.op > this.animationData.op) {
  197. this.animationData.op = data.op;
  198. this.totalFrames = Math.floor(data.op - this.animationData.ip);
  199. }
  200. var layers = this.animationData.layers;
  201. var i;
  202. var len = layers.length;
  203. var newLayers = data.layers;
  204. var j;
  205. var jLen = newLayers.length;
  206. for (j = 0; j < jLen; j += 1) {
  207. i = 0;
  208. while (i < len) {
  209. if (layers[i].id === newLayers[j].id) {
  210. layers[i] = newLayers[j];
  211. break;
  212. }
  213. i += 1;
  214. }
  215. }
  216. if (data.chars || data.fonts) {
  217. this.renderer.globalData.fontManager.addChars(data.chars);
  218. this.renderer.globalData.fontManager.addFonts(data.fonts, this.renderer.globalData.defs);
  219. }
  220. if (data.assets) {
  221. len = data.assets.length;
  222. for (i = 0; i < len; i += 1) {
  223. this.animationData.assets.push(data.assets[i]);
  224. }
  225. }
  226. this.animationData.__complete = false;
  227. dataManager.completeAnimation(
  228. this.animationData,
  229. this.onSegmentComplete
  230. );
  231. };
  232. AnimationItem.prototype.onSegmentComplete = function (data) {
  233. this.animationData = data;
  234. var expressionsPlugin = getExpressionsPlugin();
  235. if (expressionsPlugin) {
  236. expressionsPlugin.initExpressions(this);
  237. }
  238. this.loadNextSegment();
  239. };
  240. AnimationItem.prototype.loadNextSegment = function () {
  241. var segments = this.animationData.segments;
  242. if (!segments || segments.length === 0 || !this.autoloadSegments) {
  243. this.trigger('data_ready');
  244. this.timeCompleted = this.totalFrames;
  245. return;
  246. }
  247. var segment = segments.shift();
  248. this.timeCompleted = segment.time * this.frameRate;
  249. var segmentPath = this.path + this.fileName + '_' + this.segmentPos + '.json';
  250. this.segmentPos += 1;
  251. dataManager.loadData(segmentPath, this.includeLayers.bind(this), function () {
  252. this.trigger('data_failed');
  253. }.bind(this));
  254. };
  255. AnimationItem.prototype.loadSegments = function () {
  256. var segments = this.animationData.segments;
  257. if (!segments) {
  258. this.timeCompleted = this.totalFrames;
  259. }
  260. this.loadNextSegment();
  261. };
  262. AnimationItem.prototype.imagesLoaded = function () {
  263. this.trigger('loaded_images');
  264. this.checkLoaded();
  265. };
  266. AnimationItem.prototype.preloadImages = function () {
  267. this.imagePreloader.setAssetsPath(this.assetsPath);
  268. this.imagePreloader.setPath(this.path);
  269. this.imagePreloader.loadAssets(this.animationData.assets, this.imagesLoaded.bind(this));
  270. };
  271. AnimationItem.prototype.configAnimation = function (animData) {
  272. if (!this.renderer) {
  273. return;
  274. }
  275. try {
  276. this.animationData = animData;
  277. if (this.initialSegment) {
  278. this.totalFrames = Math.floor(this.initialSegment[1] - this.initialSegment[0]);
  279. this.firstFrame = Math.round(this.initialSegment[0]);
  280. } else {
  281. this.totalFrames = Math.floor(this.animationData.op - this.animationData.ip);
  282. this.firstFrame = Math.round(this.animationData.ip);
  283. }
  284. this.renderer.configAnimation(animData);
  285. if (!animData.assets) {
  286. animData.assets = [];
  287. }
  288. this.assets = this.animationData.assets;
  289. this.frameRate = this.animationData.fr;
  290. this.frameMult = this.animationData.fr / 1000;
  291. this.renderer.searchExtraCompositions(animData.assets);
  292. this.markers = markerParser(animData.markers || []);
  293. this.trigger('config_ready');
  294. this.preloadImages();
  295. this.loadSegments();
  296. this.updaFrameModifier();
  297. this.waitForFontsLoaded();
  298. if (this.isPaused) {
  299. this.audioController.pause();
  300. }
  301. } catch (error) {
  302. this.triggerConfigError(error);
  303. }
  304. };
  305. AnimationItem.prototype.waitForFontsLoaded = function () {
  306. if (!this.renderer) {
  307. return;
  308. }
  309. if (this.renderer.globalData.fontManager.isLoaded) {
  310. this.checkLoaded();
  311. } else {
  312. setTimeout(this.waitForFontsLoaded.bind(this), 20);
  313. }
  314. };
  315. AnimationItem.prototype.checkLoaded = function () {
  316. if (!this.isLoaded
  317. && this.renderer.globalData.fontManager.isLoaded
  318. && (this.imagePreloader.loadedImages() || this.renderer.rendererType !== 'canvas')
  319. && (this.imagePreloader.loadedFootages())
  320. ) {
  321. this.isLoaded = true;
  322. var expressionsPlugin = getExpressionsPlugin();
  323. if (expressionsPlugin) {
  324. expressionsPlugin.initExpressions(this);
  325. }
  326. this.renderer.initItems();
  327. setTimeout(function () {
  328. this.trigger('DOMLoaded');
  329. }.bind(this), 0);
  330. this.gotoFrame();
  331. if (this.autoplay) {
  332. this.play();
  333. }
  334. }
  335. };
  336. AnimationItem.prototype.resize = function (width, height) {
  337. // Adding this validation for backwards compatibility in case an event object was being passed down
  338. var _width = typeof width === 'number' ? width : undefined;
  339. var _height = typeof height === 'number' ? height : undefined;
  340. this.renderer.updateContainerSize(_width, _height);
  341. };
  342. AnimationItem.prototype.setSubframe = function (flag) {
  343. this.isSubframeEnabled = !!flag;
  344. };
  345. AnimationItem.prototype.gotoFrame = function () {
  346. this.currentFrame = this.isSubframeEnabled ? this.currentRawFrame : ~~this.currentRawFrame; // eslint-disable-line no-bitwise
  347. if (this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted) {
  348. this.currentFrame = this.timeCompleted;
  349. }
  350. this.trigger('enterFrame');
  351. this.renderFrame();
  352. this.trigger('drawnFrame');
  353. };
  354. AnimationItem.prototype.renderFrame = function () {
  355. if (this.isLoaded === false || !this.renderer) {
  356. return;
  357. }
  358. try {
  359. if (this.expressionsPlugin) {
  360. this.expressionsPlugin.resetFrame();
  361. }
  362. this.renderer.renderFrame(this.currentFrame + this.firstFrame);
  363. } catch (error) {
  364. this.triggerRenderFrameError(error);
  365. }
  366. };
  367. AnimationItem.prototype.play = function (name) {
  368. if (name && this.name !== name) {
  369. return;
  370. }
  371. if (this.isPaused === true) {
  372. this.isPaused = false;
  373. this.trigger('_play');
  374. this.audioController.resume();
  375. if (this._idle) {
  376. this._idle = false;
  377. this.trigger('_active');
  378. }
  379. }
  380. };
  381. AnimationItem.prototype.pause = function (name) {
  382. if (name && this.name !== name) {
  383. return;
  384. }
  385. if (this.isPaused === false) {
  386. this.isPaused = true;
  387. this.trigger('_pause');
  388. this._idle = true;
  389. this.trigger('_idle');
  390. this.audioController.pause();
  391. }
  392. };
  393. AnimationItem.prototype.togglePause = function (name) {
  394. if (name && this.name !== name) {
  395. return;
  396. }
  397. if (this.isPaused === true) {
  398. this.play();
  399. } else {
  400. this.pause();
  401. }
  402. };
  403. AnimationItem.prototype.stop = function (name) {
  404. if (name && this.name !== name) {
  405. return;
  406. }
  407. this.pause();
  408. this.playCount = 0;
  409. this._completedLoop = false;
  410. this.setCurrentRawFrameValue(0);
  411. };
  412. AnimationItem.prototype.getMarkerData = function (markerName) {
  413. var marker;
  414. for (var i = 0; i < this.markers.length; i += 1) {
  415. marker = this.markers[i];
  416. if (marker.payload && marker.payload.name === markerName) {
  417. return marker;
  418. }
  419. }
  420. return null;
  421. };
  422. AnimationItem.prototype.goToAndStop = function (value, isFrame, name) {
  423. if (name && this.name !== name) {
  424. return;
  425. }
  426. var numValue = Number(value);
  427. if (isNaN(numValue)) {
  428. var marker = this.getMarkerData(value);
  429. if (marker) {
  430. this.goToAndStop(marker.time, true);
  431. }
  432. } else if (isFrame) {
  433. this.setCurrentRawFrameValue(value);
  434. } else {
  435. this.setCurrentRawFrameValue(value * this.frameModifier);
  436. }
  437. this.pause();
  438. };
  439. AnimationItem.prototype.goToAndPlay = function (value, isFrame, name) {
  440. if (name && this.name !== name) {
  441. return;
  442. }
  443. var numValue = Number(value);
  444. if (isNaN(numValue)) {
  445. var marker = this.getMarkerData(value);
  446. if (marker) {
  447. if (!marker.duration) {
  448. this.goToAndStop(marker.time, true);
  449. } else {
  450. this.playSegments([marker.time, marker.time + marker.duration], true);
  451. }
  452. }
  453. } else {
  454. this.goToAndStop(numValue, isFrame, name);
  455. }
  456. this.play();
  457. };
  458. AnimationItem.prototype.advanceTime = function (value) {
  459. if (this.isPaused === true || this.isLoaded === false) {
  460. return;
  461. }
  462. var nextValue = this.currentRawFrame + value * this.frameModifier;
  463. var _isComplete = false;
  464. // Checking if nextValue > totalFrames - 1 for addressing non looping and looping animations.
  465. // If animation won't loop, it should stop at totalFrames - 1. If it will loop it should complete the last frame and then loop.
  466. if (nextValue >= this.totalFrames - 1 && this.frameModifier > 0) {
  467. if (!this.loop || this.playCount === this.loop) {
  468. if (!this.checkSegments(nextValue > this.totalFrames ? nextValue % this.totalFrames : 0)) {
  469. _isComplete = true;
  470. nextValue = this.totalFrames - 1;
  471. }
  472. } else if (nextValue >= this.totalFrames) {
  473. this.playCount += 1;
  474. if (!this.checkSegments(nextValue % this.totalFrames)) {
  475. this.setCurrentRawFrameValue(nextValue % this.totalFrames);
  476. this._completedLoop = true;
  477. this.trigger('loopComplete');
  478. }
  479. } else {
  480. this.setCurrentRawFrameValue(nextValue);
  481. }
  482. } else if (nextValue < 0) {
  483. if (!this.checkSegments(nextValue % this.totalFrames)) {
  484. if (this.loop && !(this.playCount-- <= 0 && this.loop !== true)) { // eslint-disable-line no-plusplus
  485. this.setCurrentRawFrameValue(this.totalFrames + (nextValue % this.totalFrames));
  486. if (!this._completedLoop) {
  487. this._completedLoop = true;
  488. } else {
  489. this.trigger('loopComplete');
  490. }
  491. } else {
  492. _isComplete = true;
  493. nextValue = 0;
  494. }
  495. }
  496. } else {
  497. this.setCurrentRawFrameValue(nextValue);
  498. }
  499. if (_isComplete) {
  500. this.setCurrentRawFrameValue(nextValue);
  501. this.pause();
  502. this.trigger('complete');
  503. }
  504. };
  505. AnimationItem.prototype.adjustSegment = function (arr, offset) {
  506. this.playCount = 0;
  507. if (arr[1] < arr[0]) {
  508. if (this.frameModifier > 0) {
  509. if (this.playSpeed < 0) {
  510. this.setSpeed(-this.playSpeed);
  511. } else {
  512. this.setDirection(-1);
  513. }
  514. }
  515. this.totalFrames = arr[0] - arr[1];
  516. this.timeCompleted = this.totalFrames;
  517. this.firstFrame = arr[1];
  518. this.setCurrentRawFrameValue(this.totalFrames - 0.001 - offset);
  519. } else if (arr[1] > arr[0]) {
  520. if (this.frameModifier < 0) {
  521. if (this.playSpeed < 0) {
  522. this.setSpeed(-this.playSpeed);
  523. } else {
  524. this.setDirection(1);
  525. }
  526. }
  527. this.totalFrames = arr[1] - arr[0];
  528. this.timeCompleted = this.totalFrames;
  529. this.firstFrame = arr[0];
  530. this.setCurrentRawFrameValue(0.001 + offset);
  531. }
  532. this.trigger('segmentStart');
  533. };
  534. AnimationItem.prototype.setSegment = function (init, end) {
  535. var pendingFrame = -1;
  536. if (this.isPaused) {
  537. if (this.currentRawFrame + this.firstFrame < init) {
  538. pendingFrame = init;
  539. } else if (this.currentRawFrame + this.firstFrame > end) {
  540. pendingFrame = end - init;
  541. }
  542. }
  543. this.firstFrame = init;
  544. this.totalFrames = end - init;
  545. this.timeCompleted = this.totalFrames;
  546. if (pendingFrame !== -1) {
  547. this.goToAndStop(pendingFrame, true);
  548. }
  549. };
  550. AnimationItem.prototype.playSegments = function (arr, forceFlag) {
  551. if (forceFlag) {
  552. this.segments.length = 0;
  553. }
  554. if (typeof arr[0] === 'object') {
  555. var i;
  556. var len = arr.length;
  557. for (i = 0; i < len; i += 1) {
  558. this.segments.push(arr[i]);
  559. }
  560. } else {
  561. this.segments.push(arr);
  562. }
  563. if (this.segments.length && forceFlag) {
  564. this.adjustSegment(this.segments.shift(), 0);
  565. }
  566. if (this.isPaused) {
  567. this.play();
  568. }
  569. };
  570. AnimationItem.prototype.resetSegments = function (forceFlag) {
  571. this.segments.length = 0;
  572. this.segments.push([this.animationData.ip, this.animationData.op]);
  573. if (forceFlag) {
  574. this.checkSegments(0);
  575. }
  576. };
  577. AnimationItem.prototype.checkSegments = function (offset) {
  578. if (this.segments.length) {
  579. this.adjustSegment(this.segments.shift(), offset);
  580. return true;
  581. }
  582. return false;
  583. };
  584. AnimationItem.prototype.destroy = function (name) {
  585. if ((name && this.name !== name) || !this.renderer) {
  586. return;
  587. }
  588. this.renderer.destroy();
  589. this.imagePreloader.destroy();
  590. this.trigger('destroy');
  591. this._cbs = null;
  592. this.onEnterFrame = null;
  593. this.onLoopComplete = null;
  594. this.onComplete = null;
  595. this.onSegmentStart = null;
  596. this.onDestroy = null;
  597. this.renderer = null;
  598. this.expressionsPlugin = null;
  599. this.imagePreloader = null;
  600. this.projectInterface = null;
  601. };
  602. AnimationItem.prototype.setCurrentRawFrameValue = function (value) {
  603. this.currentRawFrame = value;
  604. this.gotoFrame();
  605. };
  606. AnimationItem.prototype.setSpeed = function (val) {
  607. this.playSpeed = val;
  608. this.updaFrameModifier();
  609. };
  610. AnimationItem.prototype.setDirection = function (val) {
  611. this.playDirection = val < 0 ? -1 : 1;
  612. this.updaFrameModifier();
  613. };
  614. AnimationItem.prototype.setLoop = function (isLooping) {
  615. this.loop = isLooping;
  616. };
  617. AnimationItem.prototype.setVolume = function (val, name) {
  618. if (name && this.name !== name) {
  619. return;
  620. }
  621. this.audioController.setVolume(val);
  622. };
  623. AnimationItem.prototype.getVolume = function () {
  624. return this.audioController.getVolume();
  625. };
  626. AnimationItem.prototype.mute = function (name) {
  627. if (name && this.name !== name) {
  628. return;
  629. }
  630. this.audioController.mute();
  631. };
  632. AnimationItem.prototype.unmute = function (name) {
  633. if (name && this.name !== name) {
  634. return;
  635. }
  636. this.audioController.unmute();
  637. };
  638. AnimationItem.prototype.updaFrameModifier = function () {
  639. this.frameModifier = this.frameMult * this.playSpeed * this.playDirection;
  640. this.audioController.setRate(this.playSpeed * this.playDirection);
  641. };
  642. AnimationItem.prototype.getPath = function () {
  643. return this.path;
  644. };
  645. AnimationItem.prototype.getAssetsPath = function (assetData) {
  646. var path = '';
  647. if (assetData.e) {
  648. path = assetData.p;
  649. } else if (this.assetsPath) {
  650. var imagePath = assetData.p;
  651. if (imagePath.indexOf('images/') !== -1) {
  652. imagePath = imagePath.split('/')[1];
  653. }
  654. path = this.assetsPath + imagePath;
  655. } else {
  656. path = this.path;
  657. path += assetData.u ? assetData.u : '';
  658. path += assetData.p;
  659. }
  660. return path;
  661. };
  662. AnimationItem.prototype.getAssetData = function (id) {
  663. var i = 0;
  664. var len = this.assets.length;
  665. while (i < len) {
  666. if (id === this.assets[i].id) {
  667. return this.assets[i];
  668. }
  669. i += 1;
  670. }
  671. return null;
  672. };
  673. AnimationItem.prototype.hide = function () {
  674. this.renderer.hide();
  675. };
  676. AnimationItem.prototype.show = function () {
  677. this.renderer.show();
  678. };
  679. AnimationItem.prototype.getDuration = function (isFrame) {
  680. return isFrame ? this.totalFrames : this.totalFrames / this.frameRate;
  681. };
  682. AnimationItem.prototype.updateDocumentData = function (path, documentData, index) {
  683. try {
  684. var element = this.renderer.getElementByPath(path);
  685. element.updateDocumentData(documentData, index);
  686. } catch (error) {
  687. // TODO: decide how to handle catch case
  688. }
  689. };
  690. AnimationItem.prototype.trigger = function (name) {
  691. if (this._cbs && this._cbs[name]) {
  692. switch (name) {
  693. case 'enterFrame':
  694. this.triggerEvent(name, new BMEnterFrameEvent(name, this.currentFrame, this.totalFrames, this.frameModifier));
  695. break;
  696. case 'drawnFrame':
  697. this.drawnFrameEvent.currentTime = this.currentFrame;
  698. this.drawnFrameEvent.totalTime = this.totalFrames;
  699. this.drawnFrameEvent.direction = this.frameModifier;
  700. this.triggerEvent(name, this.drawnFrameEvent);
  701. break;
  702. case 'loopComplete':
  703. this.triggerEvent(name, new BMCompleteLoopEvent(name, this.loop, this.playCount, this.frameMult));
  704. break;
  705. case 'complete':
  706. this.triggerEvent(name, new BMCompleteEvent(name, this.frameMult));
  707. break;
  708. case 'segmentStart':
  709. this.triggerEvent(name, new BMSegmentStartEvent(name, this.firstFrame, this.totalFrames));
  710. break;
  711. case 'destroy':
  712. this.triggerEvent(name, new BMDestroyEvent(name, this));
  713. break;
  714. default:
  715. this.triggerEvent(name);
  716. }
  717. }
  718. if (name === 'enterFrame' && this.onEnterFrame) {
  719. this.onEnterFrame.call(this, new BMEnterFrameEvent(name, this.currentFrame, this.totalFrames, this.frameMult));
  720. }
  721. if (name === 'loopComplete' && this.onLoopComplete) {
  722. this.onLoopComplete.call(this, new BMCompleteLoopEvent(name, this.loop, this.playCount, this.frameMult));
  723. }
  724. if (name === 'complete' && this.onComplete) {
  725. this.onComplete.call(this, new BMCompleteEvent(name, this.frameMult));
  726. }
  727. if (name === 'segmentStart' && this.onSegmentStart) {
  728. this.onSegmentStart.call(this, new BMSegmentStartEvent(name, this.firstFrame, this.totalFrames));
  729. }
  730. if (name === 'destroy' && this.onDestroy) {
  731. this.onDestroy.call(this, new BMDestroyEvent(name, this));
  732. }
  733. };
  734. AnimationItem.prototype.triggerRenderFrameError = function (nativeError) {
  735. var error = new BMRenderFrameErrorEvent(nativeError, this.currentFrame);
  736. this.triggerEvent('error', error);
  737. if (this.onError) {
  738. this.onError.call(this, error);
  739. }
  740. };
  741. AnimationItem.prototype.triggerConfigError = function (nativeError) {
  742. var error = new BMConfigErrorEvent(nativeError, this.currentFrame);
  743. this.triggerEvent('error', error);
  744. if (this.onError) {
  745. this.onError.call(this, error);
  746. }
  747. };
  748. export default AnimationItem;