worker_wrapper.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. function workerContent() {
  2. function extendPrototype(sources, destination) {
  3. var i;
  4. var len = sources.length;
  5. var sourcePrototype;
  6. for (i = 0; i < len; i += 1) {
  7. sourcePrototype = sources[i].prototype;
  8. for (var attr in sourcePrototype) {
  9. if (Object.prototype.hasOwnProperty.call(sourcePrototype, attr)) destination.prototype[attr] = sourcePrototype[attr];
  10. }
  11. }
  12. }
  13. function ProxyElement(type, namespace) {
  14. this._state = 'init';
  15. this._isDirty = false;
  16. this._isProxy = true;
  17. this._changedStyles = [];
  18. this._changedAttributes = [];
  19. this._changedElements = [];
  20. this._textContent = null;
  21. this.type = type;
  22. this.namespace = namespace;
  23. this.children = [];
  24. localIdCounter += 1;
  25. this.attributes = {
  26. id: 'l_d_' + localIdCounter,
  27. };
  28. this.style = new Style(this);
  29. }
  30. ProxyElement.prototype = {
  31. appendChild: function (_child) {
  32. _child.parentNode = this;
  33. this.children.push(_child);
  34. this._isDirty = true;
  35. this._changedElements.push([_child, this.attributes.id]);
  36. },
  37. insertBefore: function (_newElement, _nextElement) {
  38. var children = this.children;
  39. for (var i = 0; i < children.length; i += 1) {
  40. if (children[i] === _nextElement) {
  41. children.splice(i, 0, _newElement);
  42. this._isDirty = true;
  43. this._changedElements.push([_newElement, this.attributes.id, _nextElement.attributes.id]);
  44. return;
  45. }
  46. }
  47. children.push(_nextElement);
  48. },
  49. setAttribute: function (_attribute, _value) {
  50. this.attributes[_attribute] = _value;
  51. if (!this._isDirty) {
  52. this._isDirty = true;
  53. }
  54. this._changedAttributes.push(_attribute);
  55. },
  56. serialize: function () {
  57. return {
  58. type: this.type,
  59. namespace: this.namespace,
  60. style: this.style.serialize(),
  61. attributes: this.attributes,
  62. children: this.children.map(function (child) { return child.serialize(); }),
  63. textContent: this._textContent,
  64. };
  65. },
  66. // eslint-disable-next-line class-methods-use-this
  67. addEventListener: function (_, _callback) {
  68. setTimeout(_callback, 1);
  69. },
  70. setAttributeNS: function (_, _attribute, _value) {
  71. this.attributes[_attribute] = _value;
  72. if (!this._isDirty) {
  73. this._isDirty = true;
  74. }
  75. this._changedAttributes.push(_attribute);
  76. },
  77. };
  78. Object.defineProperty(ProxyElement.prototype, 'textContent', {
  79. set: function (_value) {
  80. this._isDirty = true;
  81. this._textContent = _value;
  82. },
  83. });
  84. var localIdCounter = 0;
  85. var animations = {};
  86. var styleProperties = ['width', 'height', 'display', 'transform', 'opacity', 'contentVisibility', 'mix-blend-mode'];
  87. function convertArguments(args) {
  88. var arr = [];
  89. var i;
  90. var len = args.length;
  91. for (i = 0; i < len; i += 1) {
  92. arr.push(args[i]);
  93. }
  94. return arr;
  95. }
  96. function Style(element) {
  97. this.element = element;
  98. }
  99. Style.prototype = {
  100. serialize: function () {
  101. var obj = {};
  102. for (var i = 0; i < styleProperties.length; i += 1) {
  103. var propertyKey = styleProperties[i];
  104. var keyName = '_' + propertyKey;
  105. if (keyName in this) {
  106. obj[propertyKey] = this[keyName];
  107. }
  108. }
  109. return obj;
  110. },
  111. };
  112. styleProperties.forEach(function (propertyKey) {
  113. Object.defineProperty(Style.prototype, propertyKey, {
  114. set: function (value) {
  115. if (!this.element._isDirty) {
  116. this.element._isDirty = true;
  117. }
  118. this.element._changedStyles.push(propertyKey);
  119. var keyName = '_' + propertyKey;
  120. this[keyName] = value;
  121. },
  122. get: function () {
  123. var keyName = '_' + propertyKey;
  124. return this[keyName];
  125. },
  126. });
  127. });
  128. function CanvasContext(element) {
  129. this.element = element;
  130. }
  131. CanvasContext.prototype = {
  132. createRadialGradient: function () {
  133. function addColorStop() {
  134. instruction.stops.push(convertArguments(arguments));
  135. }
  136. var instruction = {
  137. t: 'rGradient',
  138. a: convertArguments(arguments),
  139. stops: [],
  140. };
  141. this.element.instructions.push(instruction);
  142. return {
  143. addColorStop: addColorStop,
  144. };
  145. },
  146. createLinearGradient: function () {
  147. function addColorStop() {
  148. instruction.stops.push(convertArguments(arguments));
  149. }
  150. var instruction = {
  151. t: 'lGradient',
  152. a: convertArguments(arguments),
  153. stops: [],
  154. };
  155. this.element.instructions.push(instruction);
  156. return {
  157. addColorStop: addColorStop,
  158. };
  159. },
  160. };
  161. Object.defineProperties(CanvasContext.prototype, {
  162. canvas: {
  163. enumerable: true,
  164. get: function () {
  165. return this.element;
  166. },
  167. },
  168. });
  169. var canvasContextMethods = [
  170. 'fillRect',
  171. 'setTransform',
  172. 'drawImage',
  173. 'beginPath',
  174. 'moveTo',
  175. 'save',
  176. 'restore',
  177. 'fillText',
  178. 'setLineDash',
  179. 'clearRect',
  180. 'clip',
  181. 'rect',
  182. 'stroke',
  183. 'fill',
  184. 'closePath',
  185. 'bezierCurveTo',
  186. 'lineTo',
  187. ];
  188. canvasContextMethods.forEach(function (method) {
  189. CanvasContext.prototype[method] = function () {
  190. this.element.instructions.push({
  191. t: method,
  192. a: convertArguments(arguments),
  193. });
  194. };
  195. });
  196. var canvasContextProperties = [
  197. 'globalAlpha',
  198. 'strokeStyle',
  199. 'fillStyle',
  200. 'lineCap',
  201. 'lineJoin',
  202. 'lineWidth',
  203. 'miterLimit',
  204. 'lineDashOffset',
  205. 'globalCompositeOperation',
  206. ];
  207. canvasContextProperties.forEach(function (property) {
  208. Object.defineProperty(CanvasContext.prototype, property,
  209. {
  210. set: function (_value) {
  211. this.element.instructions.push({
  212. t: property,
  213. a: _value,
  214. });
  215. },
  216. });
  217. });
  218. function CanvasElement(type, namespace) {
  219. ProxyElement.call(this, type, namespace);
  220. this.instructions = [];
  221. this.width = 0;
  222. this.height = 0;
  223. this.context = new CanvasContext(this);
  224. }
  225. CanvasElement.prototype = {
  226. getContext: function () {
  227. return this.context;
  228. },
  229. resetInstructions: function () {
  230. this.instructions.length = 0;
  231. },
  232. };
  233. extendPrototype([ProxyElement], CanvasElement);
  234. function createElement(namespace, type) {
  235. if (type === 'canvas') {
  236. return new CanvasElement(type, namespace);
  237. }
  238. return new ProxyElement(type, namespace);
  239. }
  240. var window = self; // eslint-disable-line no-redeclare, no-unused-vars
  241. var document = { // eslint-disable-line no-redeclare
  242. createElementNS: function (namespace, type) {
  243. return createElement(namespace, type);
  244. },
  245. createElement: function (type) {
  246. return createElement('', type);
  247. },
  248. getElementsByTagName: function () {
  249. return [];
  250. },
  251. body: createElement('', 'body'),
  252. _isProxy: true,
  253. };
  254. /* eslint-enable */
  255. var lottieInternal = (function () {
  256. 'use strict';
  257. /* <%= contents %> */
  258. function addElementToList(element, list) {
  259. list.push(element);
  260. element._isDirty = false;
  261. element._changedStyles.length = 0;
  262. element._changedAttributes.length = 0;
  263. element._changedElements.length = 0;
  264. element._textContent = null;
  265. element.children.forEach(function (child) {
  266. addElementToList(child, list);
  267. });
  268. }
  269. function addChangedAttributes(element) {
  270. var changedAttributes = element._changedAttributes;
  271. var attributes = [];
  272. var attribute;
  273. for (var i = 0; i < changedAttributes.length; i += 1) {
  274. attribute = changedAttributes[i];
  275. attributes.push([attribute, element.attributes[attribute]]);
  276. }
  277. return attributes;
  278. }
  279. function addChangedStyles(element) {
  280. var changedStyles = element._changedStyles;
  281. var styles = [];
  282. var style;
  283. for (var i = 0; i < changedStyles.length; i += 1) {
  284. style = changedStyles[i];
  285. styles.push([style, element.style[style]]);
  286. }
  287. return styles;
  288. }
  289. function addChangedElements(element, elements) {
  290. var changedElements = element._changedElements;
  291. var elementsList = [];
  292. var elementData;
  293. for (var i = 0; i < changedElements.length; i += 1) {
  294. elementData = changedElements[i];
  295. elementsList.push([elementData[0].serialize(), elementData[1], elementData[2]]);
  296. addElementToList(elementData[0], elements);
  297. }
  298. return elementsList;
  299. }
  300. function loadAnimation(payload) {
  301. var params = payload.params;
  302. var wrapper;
  303. var animation;
  304. var elements = [];
  305. var canvas;
  306. if (params.renderer === 'svg') {
  307. wrapper = document.createElement('div');
  308. params.container = wrapper;
  309. } else {
  310. canvas = params.rendererSettings.canvas;
  311. if (!canvas) {
  312. canvas = document.createElement('canvas');
  313. canvas.width = params.animationData.w;
  314. canvas.height = params.animationData.h;
  315. }
  316. var ctx = canvas.getContext('2d');
  317. params.rendererSettings.context = ctx;
  318. }
  319. animation = lottie.loadAnimation(params);
  320. animation.addEventListener('error', function (error) {
  321. console.log(error); // eslint-disable-line
  322. });
  323. animation.onError = function (error) {
  324. console.log('ERRORO', error); // eslint-disable-line
  325. };
  326. animation.addEventListener('_play', function () {
  327. self.postMessage({
  328. type: 'playing',
  329. payload: {
  330. id: payload.id,
  331. },
  332. });
  333. });
  334. animation.addEventListener('_pause', function () {
  335. self.postMessage({
  336. type: 'paused',
  337. payload: {
  338. id: payload.id,
  339. },
  340. });
  341. });
  342. if (params.renderer === 'svg') {
  343. animation.addEventListener('DOMLoaded', function () {
  344. var serialized = wrapper.serialize();
  345. addElementToList(wrapper, elements);
  346. self.postMessage({
  347. type: 'SVGloaded',
  348. payload: {
  349. id: payload.id,
  350. tree: serialized.children[0],
  351. },
  352. });
  353. });
  354. animation.addEventListener('drawnFrame', function (event) {
  355. var changedElements = [];
  356. var element;
  357. for (var i = 0; i < elements.length; i += 1) {
  358. element = elements[i];
  359. if (element._isDirty) {
  360. var changedElement = {
  361. id: element.attributes.id,
  362. styles: addChangedStyles(element),
  363. attributes: addChangedAttributes(element),
  364. elements: addChangedElements(element, elements),
  365. textContent: element._textContent || undefined,
  366. };
  367. changedElements.push(changedElement);
  368. element._isDirty = false;
  369. element._changedAttributes.length = 0;
  370. element._changedStyles.length = 0;
  371. element._changedElements.length = 0;
  372. element._textContent = null;
  373. }
  374. }
  375. self.postMessage({
  376. type: 'SVGupdated',
  377. payload: {
  378. elements: changedElements,
  379. id: payload.id,
  380. currentTime: event.currentTime,
  381. },
  382. });
  383. });
  384. } else if (canvas._isProxy) {
  385. animation.addEventListener('drawnFrame', function (event) {
  386. self.postMessage({
  387. type: 'CanvasUpdated',
  388. payload: {
  389. instructions: canvas.instructions,
  390. id: payload.id,
  391. currentTime: event.currentTime,
  392. },
  393. });
  394. canvas.resetInstructions();
  395. });
  396. }
  397. animation.addEventListener('DOMLoaded', function () {
  398. self.postMessage({
  399. type: 'DOMLoaded',
  400. payload: {
  401. id: payload.id,
  402. totalFrames: animation.totalFrames,
  403. frameRate: animation.frameRate,
  404. firstFrame: animation.firstFrame,
  405. currentFrame: animation.currentFrame,
  406. playDirection: animation.playDirection,
  407. isSubframeEnabled: animation.isSubframeEnabled,
  408. currentRawFrame: animation.currentRawFrame,
  409. timeCompleted: animation.timeCompleted,
  410. },
  411. });
  412. });
  413. animations[payload.id] = {
  414. animation: animation,
  415. events: {},
  416. };
  417. }
  418. return {
  419. loadAnimation: loadAnimation,
  420. };
  421. }({}));
  422. onmessage = function (evt) {
  423. var data = evt.data;
  424. var type = data.type;
  425. var payload = data.payload;
  426. if (type === 'load') {
  427. lottieInternal.loadAnimation(payload);
  428. } else if (type === 'pause') {
  429. if (animations[payload.id]) {
  430. animations[payload.id].animation.pause();
  431. }
  432. } else if (type === 'play') {
  433. if (animations[payload.id]) {
  434. animations[payload.id].animation.play();
  435. }
  436. } else if (type === 'stop') {
  437. if (animations[payload.id]) {
  438. animations[payload.id].animation.stop();
  439. }
  440. } else if (type === 'setSpeed') {
  441. if (animations[payload.id]) {
  442. animations[payload.id].animation.setSpeed(payload.value);
  443. }
  444. } else if (type === 'setDirection') {
  445. if (animations[payload.id]) {
  446. animations[payload.id].animation.setDirection(payload.value);
  447. }
  448. } else if (type === 'setLoop') {
  449. if (animations[payload.id]) {
  450. animations[payload.id].animation.setLoop(payload.value);
  451. }
  452. } else if (type === 'goToAndPlay') {
  453. if (animations[payload.id]) {
  454. animations[payload.id].animation.goToAndPlay(payload.value, payload.isFrame);
  455. }
  456. } else if (type === 'goToAndStop') {
  457. if (animations[payload.id]) {
  458. animations[payload.id].animation.goToAndStop(payload.value, payload.isFrame);
  459. }
  460. } else if (type === 'setSubframe') {
  461. if (animations[payload.id]) {
  462. animations[payload.id].animation.setSubframe(payload.value);
  463. }
  464. } else if (type === 'addEventListener') {
  465. if (animations[payload.id]) {
  466. var eventCallback = function () {
  467. self.postMessage({
  468. type: 'event',
  469. payload: {
  470. id: payload.id,
  471. callbackId: payload.callbackId,
  472. argument: arguments[0],
  473. },
  474. });
  475. };
  476. animations[payload.id].events[payload.callbackId] = {
  477. callback: eventCallback,
  478. };
  479. animations[payload.id].animation.addEventListener(payload.eventName, eventCallback);
  480. }
  481. } else if (type === 'removeEventListener') {
  482. if (animations[payload.id]) {
  483. var callback = animations[payload.id].events[payload.callbackId];
  484. animations[payload.id].animation.removeEventListener(payload.eventName, callback);
  485. }
  486. } else if (type === 'destroy') {
  487. if (animations[payload.id]) {
  488. animations[payload.id].animation.destroy();
  489. animations[payload.id] = null;
  490. }
  491. } else if (type === 'resize') {
  492. if (animations[payload.id]) {
  493. animations[payload.id].animation.resize(payload.width, payload.height);
  494. }
  495. } else if (type === 'playSegments') {
  496. if (animations[payload.id]) {
  497. animations[payload.id].animation.playSegments(payload.arr, payload.forceFlag);
  498. }
  499. } else if (type === 'resetSegments') {
  500. if (animations[payload.id]) {
  501. animations[payload.id].animation.resetSegments(payload.forceFlag);
  502. }
  503. } else if (type === 'updateDocumentData') {
  504. animations[payload.id].animation.updateDocumentData(payload.path, payload.documentData, payload.index);
  505. }
  506. };
  507. }
  508. function createWorker(fn) {
  509. var blob = new Blob(['(' + fn.toString() + '())'], { type: 'text/javascript' });
  510. var url = URL.createObjectURL(blob);
  511. return new Worker(url);
  512. }
  513. // eslint-disable-next-line no-unused-vars
  514. var lottie = (function () {
  515. 'use strict';
  516. var workerInstance = createWorker(workerContent);
  517. var animationIdCounter = 0;
  518. var eventsIdCounter = 0;
  519. var animations = {};
  520. var defaultSettings = {
  521. rendererSettings: {},
  522. };
  523. function createTree(data, container, map, afterElement) {
  524. var elem;
  525. if (data.type === 'div') {
  526. elem = document.createElement('div');
  527. } else {
  528. elem = document.createElementNS(data.namespace, data.type);
  529. }
  530. if (data.textContent) {
  531. elem.textContent = data.textContent;
  532. }
  533. for (var attr in data.attributes) {
  534. if (Object.prototype.hasOwnProperty.call(data.attributes, attr)) {
  535. if (attr === 'href') {
  536. elem.setAttributeNS('http://www.w3.org/1999/xlink', attr, data.attributes[attr]);
  537. } else {
  538. elem.setAttribute(attr, data.attributes[attr]);
  539. }
  540. if (attr === 'id') {
  541. map[data.attributes[attr]] = elem;
  542. }
  543. }
  544. }
  545. for (var style in data.style) {
  546. if (Object.prototype.hasOwnProperty.call(data.style, style)) {
  547. elem.style[style] = data.style[style];
  548. }
  549. }
  550. data.children.forEach(function (element) {
  551. createTree(element, elem, map);
  552. });
  553. if (!afterElement) {
  554. container.appendChild(elem);
  555. } else {
  556. container.insertBefore(elem, afterElement);
  557. }
  558. }
  559. var handleAnimationLoaded = (function () {
  560. return function (payload) {
  561. var animation = animations[payload.id];
  562. animation._loaded = true;
  563. // if callbacks have been added before the animation has loaded
  564. animation.pendingCallbacks.forEach(function (callbackData) {
  565. animation.animInstance.addEventListener(callbackData.eventName, callbackData.callback);
  566. if (callbackData.eventName === 'DOMLoaded') {
  567. callbackData.callback();
  568. }
  569. });
  570. animation.animInstance.totalFrames = payload.totalFrames;
  571. animation.animInstance.frameRate = payload.frameRate;
  572. animation.animInstance.firstFrame = payload.firstFrame;
  573. animation.animInstance.playDirection = payload.playDirection;
  574. animation.animInstance.currentFrame = payload.isSubframeEnabled ? payload.currentRawFrame : ~~payload.currentRawFrame; // eslint-disable-line no-bitwise
  575. if (payload.timeCompleted !== payload.totalFrames && payload.currentFrame > payload.timeCompleted) {
  576. animation.animInstance.currentFrame = payload.timeCompleted;
  577. }
  578. };
  579. }());
  580. var handleSVGLoaded = (function () {
  581. return function (payload) {
  582. var animation = animations[payload.id];
  583. var container = animation.container;
  584. var elements = animation.elements;
  585. createTree(payload.tree, container, elements);
  586. };
  587. }());
  588. function addNewElements(newElements, elements) {
  589. var element;
  590. for (var i = 0; i < newElements.length; i += 1) {
  591. element = newElements[i];
  592. var parent = elements[element[1]];
  593. if (parent) {
  594. var sibling;
  595. if (element[2]) {
  596. sibling = elements[element[2]];
  597. }
  598. createTree(element[0], parent, elements, sibling);
  599. newElements.splice(i, 1);
  600. i -= 1;
  601. }
  602. }
  603. }
  604. function updateElementStyles(element, styles) {
  605. var style;
  606. for (var i = 0; i < styles.length; i += 1) {
  607. style = styles[i];
  608. element.style[style[0]] = style[1];
  609. }
  610. }
  611. function updateElementAttributes(element, attributes) {
  612. var attribute;
  613. for (var i = 0; i < attributes.length; i += 1) {
  614. attribute = attributes[i];
  615. element.setAttribute(attribute[0], attribute[1]);
  616. }
  617. }
  618. function updateTextContent(element, text) {
  619. if (text) {
  620. element.textContent = text;
  621. }
  622. }
  623. function handleAnimationUpdate(payload) {
  624. var changedElements = payload.elements;
  625. var animation = animations[payload.id];
  626. if (animation) {
  627. var elements = animation.elements;
  628. var elementData;
  629. for (var i = 0; i < changedElements.length; i += 1) {
  630. elementData = changedElements[i];
  631. var element = elements[elementData.id];
  632. addNewElements(elementData.elements, elements);
  633. updateElementStyles(element, elementData.styles);
  634. updateElementAttributes(element, elementData.attributes);
  635. updateTextContent(element, elementData.textContent);
  636. }
  637. animation.animInstance.currentFrame = payload.currentTime;
  638. }
  639. }
  640. function createInstructionsHandler(canvas) {
  641. var ctx = canvas.getContext('2d');
  642. var map = {
  643. beginPath: ctx.beginPath,
  644. closePath: ctx.closePath,
  645. rect: ctx.rect,
  646. clip: ctx.clip,
  647. clearRect: ctx.clearRect,
  648. setTransform: ctx.setTransform,
  649. moveTo: ctx.moveTo,
  650. bezierCurveTo: ctx.bezierCurveTo,
  651. lineTo: ctx.lineTo,
  652. fill: ctx.fill,
  653. save: ctx.save,
  654. restore: ctx.restore,
  655. };
  656. return function (instructions) {
  657. for (var i = 0; i < instructions.length; i += 1) {
  658. var instruction = instructions[i];
  659. var fn = map[instruction.t];
  660. if (fn) {
  661. fn.apply(ctx, instruction.a);
  662. } else {
  663. ctx[instruction.t] = instruction.a;
  664. }
  665. }
  666. };
  667. }
  668. function handleCanvasAnimationUpdate(payload) {
  669. var animation = animations[payload.id];
  670. animation.instructionsHandler(payload.instructions);
  671. }
  672. function handleEvent(payload) {
  673. var animation = animations[payload.id];
  674. if (animation) {
  675. var callbacks = animation.callbacks;
  676. if (callbacks[payload.callbackId]) {
  677. callbacks[payload.callbackId].callback(payload.argument);
  678. }
  679. }
  680. }
  681. function handlePlaying(payload) {
  682. var animation = animations[payload.id];
  683. if (animation) {
  684. animation.animInstance.isPaused = false;
  685. }
  686. }
  687. function handlePaused(payload) {
  688. var animation = animations[payload.id];
  689. if (animation) {
  690. animation.animInstance.isPaused = true;
  691. }
  692. }
  693. var messageHandlers = {
  694. DOMLoaded: handleAnimationLoaded,
  695. SVGloaded: handleSVGLoaded,
  696. SVGupdated: handleAnimationUpdate,
  697. CanvasUpdated: handleCanvasAnimationUpdate,
  698. event: handleEvent,
  699. playing: handlePlaying,
  700. paused: handlePaused,
  701. };
  702. workerInstance.onmessage = function (event) {
  703. if (messageHandlers[event.data.type]) {
  704. messageHandlers[event.data.type](event.data.payload);
  705. }
  706. };
  707. function resolveAnimationData(params) {
  708. return new Promise(function (resolve, reject) {
  709. var paramsCopy = Object.assign({}, defaultSettings, params);
  710. if (paramsCopy.animType && !paramsCopy.renderer) {
  711. paramsCopy.renderer = paramsCopy.animType;
  712. }
  713. if (paramsCopy.wrapper) {
  714. if (!paramsCopy.container) {
  715. paramsCopy.container = paramsCopy.wrapper;
  716. }
  717. delete paramsCopy.wrapper;
  718. }
  719. if (paramsCopy.animationData) {
  720. resolve(paramsCopy);
  721. } else if (paramsCopy.path) {
  722. fetch(paramsCopy.path)
  723. .then(function (response) {
  724. return response.json();
  725. })
  726. .then(function (animationData) {
  727. paramsCopy.animationData = animationData;
  728. delete paramsCopy.path;
  729. resolve(paramsCopy);
  730. });
  731. } else {
  732. reject();
  733. }
  734. });
  735. }
  736. function loadAnimation(params) {
  737. animationIdCounter += 1;
  738. var animationId = 'lottie_animationId_' + animationIdCounter;
  739. var animation = {
  740. elements: {},
  741. callbacks: {},
  742. pendingCallbacks: [],
  743. status: 'init',
  744. };
  745. var animInstance = {
  746. id: animationId,
  747. isPaused: true,
  748. pause: function () {
  749. workerInstance.postMessage({
  750. type: 'pause',
  751. payload: {
  752. id: animationId,
  753. },
  754. });
  755. },
  756. play: function () {
  757. workerInstance.postMessage({
  758. type: 'play',
  759. payload: {
  760. id: animationId,
  761. },
  762. });
  763. },
  764. stop: function () {
  765. workerInstance.postMessage({
  766. type: 'stop',
  767. payload: {
  768. id: animationId,
  769. },
  770. });
  771. },
  772. setSpeed: function (value) {
  773. workerInstance.postMessage({
  774. type: 'setSpeed',
  775. payload: {
  776. id: animationId,
  777. value: value,
  778. },
  779. });
  780. },
  781. setDirection: function (value) {
  782. workerInstance.postMessage({
  783. type: 'setDirection',
  784. payload: {
  785. id: animationId,
  786. value: value,
  787. },
  788. });
  789. },
  790. setLoop: function (value) {
  791. workerInstance.postMessage({
  792. type: 'setLoop',
  793. payload: {
  794. id: animationId,
  795. value: value,
  796. },
  797. });
  798. },
  799. goToAndStop: function (value, isFrame) {
  800. workerInstance.postMessage({
  801. type: 'goToAndStop',
  802. payload: {
  803. id: animationId,
  804. value: value,
  805. isFrame: isFrame,
  806. },
  807. });
  808. },
  809. goToAndPlay: function (value, isFrame) {
  810. workerInstance.postMessage({
  811. type: 'goToAndPlay',
  812. payload: {
  813. id: animationId,
  814. value: value,
  815. isFrame: isFrame,
  816. },
  817. });
  818. },
  819. playSegments: function (arr, forceFlag) {
  820. workerInstance.postMessage({
  821. type: 'playSegments',
  822. payload: {
  823. id: animationId,
  824. arr: arr,
  825. forceFlag: forceFlag,
  826. },
  827. });
  828. },
  829. setSubframe: function (value) {
  830. workerInstance.postMessage({
  831. type: 'setSubframe',
  832. payload: {
  833. id: animationId,
  834. value: value,
  835. },
  836. });
  837. },
  838. addEventListener: function (eventName, callback) {
  839. if (!animation._loaded) {
  840. animation.pendingCallbacks.push({
  841. eventName: eventName,
  842. callback: callback,
  843. });
  844. } else {
  845. eventsIdCounter += 1;
  846. var callbackId = 'callback_' + eventsIdCounter;
  847. animation.callbacks[callbackId] = {
  848. eventName: eventName,
  849. callback: callback,
  850. };
  851. workerInstance.postMessage({
  852. type: 'addEventListener',
  853. payload: {
  854. id: animationId,
  855. callbackId: callbackId,
  856. eventName: eventName,
  857. },
  858. });
  859. }
  860. },
  861. removeEventListener: function (eventName, callback) {
  862. Object.keys(animation.callbacks)
  863. .forEach(function (key) {
  864. if (animation.callbacks[key].eventName === eventName
  865. && (animation.callbacks[key].callback === callback || !callback)) {
  866. delete animation.callbacks[key];
  867. workerInstance.postMessage({
  868. type: 'removeEventListener',
  869. payload: {
  870. id: animationId,
  871. callbackId: key,
  872. eventName: eventName,
  873. },
  874. });
  875. }
  876. });
  877. },
  878. destroy: function () {
  879. if (animation.status === 'init') {
  880. animation.status = 'destroyable';
  881. } else {
  882. animation.status = 'destroyed';
  883. animations[animationId] = null;
  884. if (animation.container) {
  885. animation.container.innerHTML = '';
  886. }
  887. workerInstance.postMessage({
  888. type: 'destroy',
  889. payload: {
  890. id: animationId,
  891. },
  892. });
  893. }
  894. },
  895. resize: function (width, height) {
  896. var devicePixelRatio = window.devicePixelRatio || 1;
  897. workerInstance.postMessage({
  898. type: 'resize',
  899. payload: {
  900. id: animationId,
  901. // Till Worker thread knows nothing about container, we've to pass it here
  902. width: width || (animation.container ? animation.container.offsetWidth * devicePixelRatio : 0),
  903. height: height || (animation.container ? animation.container.offsetHeight * devicePixelRatio : 0),
  904. },
  905. });
  906. },
  907. updateDocumentData: function (path, documentData, index) {
  908. workerInstance.postMessage({
  909. type: 'updateDocumentData',
  910. payload: {
  911. id: animationId,
  912. path: path,
  913. documentData: documentData,
  914. index: index,
  915. },
  916. });
  917. },
  918. };
  919. animation.animInstance = animInstance;
  920. resolveAnimationData(params)
  921. .then(function (animationParams) {
  922. if (animation.status === 'destroyable') {
  923. animation.animInstance.destroy();
  924. return;
  925. }
  926. animation.status = 'loaded';
  927. var transferedObjects = [];
  928. if (animationParams.container) {
  929. animation.container = animationParams.container;
  930. delete animationParams.container;
  931. }
  932. if (animationParams.renderer === 'canvas') {
  933. var canvas = animationParams.rendererSettings.canvas;
  934. // If no custom canvas was passed
  935. if (!canvas) {
  936. var devicePixelRatio = window.devicePixelRatio || 1;
  937. canvas = document.createElement('canvas');
  938. animation.container.appendChild(canvas);
  939. canvas.width = (animation.container ? animation.container.offsetWidth : animationParams.animationData.w) * devicePixelRatio;
  940. canvas.height = (animation.container ? animation.container.offsetHeight : animationParams.animationData.h) * devicePixelRatio;
  941. canvas.style.width = '100%';
  942. canvas.style.height = '100%';
  943. }
  944. // Transfer control to offscreen if it's not already
  945. var transferCanvas = canvas;
  946. if (typeof OffscreenCanvas === 'undefined') {
  947. animation.canvas = canvas;
  948. animation.instructionsHandler = createInstructionsHandler(canvas);
  949. } else {
  950. if (!(canvas instanceof OffscreenCanvas)) {
  951. transferCanvas = canvas.transferControlToOffscreen();
  952. animationParams.rendererSettings.canvas = transferCanvas;
  953. }
  954. transferedObjects.push(transferCanvas);
  955. }
  956. }
  957. animations[animationId] = animation;
  958. workerInstance.postMessage({
  959. type: 'load',
  960. payload: {
  961. params: animationParams,
  962. id: animationId,
  963. },
  964. }, transferedObjects);
  965. });
  966. return animInstance;
  967. }
  968. var lottiejs = {
  969. loadAnimation: loadAnimation,
  970. };
  971. return lottiejs;
  972. }());