├── .gitignore ├── .npmignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── build └── lottie_canvas.js ├── demo ├── index.js └── test │ ├── data1 │ ├── d0.json │ ├── d1.json │ ├── d10.json │ ├── d2.json │ ├── d3.json │ ├── d4.json │ ├── d5.json │ ├── d6.json │ ├── d7.json │ ├── d8.json │ └── d9.json │ ├── data2 │ ├── d1.json │ ├── d10.json │ ├── d11.json │ ├── d12.json │ ├── d13.json │ ├── d14.json │ ├── d15.json │ ├── d16.json │ ├── d17.json │ ├── d18.json │ ├── d19.json │ ├── d2.json │ ├── d20.json │ ├── d21.json │ ├── d22.json │ ├── d3.json │ ├── d4.json │ ├── d5.json │ ├── d6.json │ ├── d7.json │ ├── d8.json │ └── d9.json │ ├── data3 │ ├── d1.json │ ├── d2.json │ ├── d3.json │ ├── d4.json │ ├── d5.json │ ├── d6.json │ ├── d7.json │ ├── d8.json │ └── images │ │ └── img_0.png │ ├── data4 │ ├── d1 │ │ ├── data.json │ │ └── images │ │ │ ├── img_0.png │ │ │ ├── img_1.png │ │ │ ├── img_2.png │ │ │ ├── img_3.png │ │ │ ├── img_4.png │ │ │ ├── img_5.png │ │ │ ├── img_6.png │ │ │ └── img_7.png │ ├── d2 │ │ ├── data.json │ │ └── images │ │ │ ├── img_0.png │ │ │ ├── img_1.png │ │ │ ├── img_2.png │ │ │ ├── img_3.png │ │ │ └── img_4.png │ ├── d3 │ │ ├── data.json │ │ └── images │ │ │ ├── img_0.png │ │ │ ├── img_1.png │ │ │ ├── img_2.png │ │ │ └── img_3.png │ ├── d4 │ │ ├── data.json │ │ └── images │ │ │ ├── img_0.png │ │ │ ├── img_1.png │ │ │ ├── img_10.png │ │ │ ├── img_11.png │ │ │ ├── img_2.png │ │ │ ├── img_3.png │ │ │ ├── img_4.png │ │ │ ├── img_5.png │ │ │ ├── img_6.png │ │ │ ├── img_7.png │ │ │ ├── img_8.png │ │ │ └── img_9.png │ ├── d5 │ │ ├── data.json │ │ └── images │ │ │ └── img_0.png │ ├── d6 │ │ ├── data.json │ │ └── images │ │ │ └── img_0.png │ ├── d7 │ │ ├── data.json │ │ └── images │ │ │ └── img_0.png │ ├── d8 │ │ ├── data.json │ │ └── images │ │ │ └── img_0.png │ └── image │ │ ├── img1.png │ │ └── img2.png │ ├── index.html │ └── ppo.min.js ├── gifs └── demo.gif ├── index.d.ts ├── package.json ├── player ├── index.html └── js │ ├── 3rd_party │ ├── BezierEaser.js │ ├── seedrandom.js │ └── transformation-matrix.js │ ├── EffectsManager.js │ ├── animation │ ├── AnimationItem.js │ └── AnimationManager.js │ ├── effects │ ├── EffectsManagerPlaceholder.js │ └── SliderEffect.js │ ├── elements │ ├── BaseElement.js │ ├── BaseTextElement.js │ ├── CompElement.js │ ├── ImageElement.js │ ├── NullElement.js │ ├── ShapeElement.js │ ├── SolidElement.js │ ├── TextElement.js │ ├── canvasElements │ │ ├── CVBaseElement.js │ │ ├── CVCompElement.js │ │ ├── CVContextData.js │ │ ├── CVEffects.js │ │ ├── CVImageElement.js │ │ ├── CVMaskElement.js │ │ ├── CVShapeElement.js │ │ ├── CVSolidElement.js │ │ └── CVTextElement.js │ ├── helpers │ │ ├── FrameElement.js │ │ ├── HierarchyElement.js │ │ ├── RenderableDOMElement.js │ │ ├── RenderableElement.js │ │ ├── TransformElement.js │ │ └── shapes │ │ │ ├── CVShapeData.js │ │ │ ├── ProcessedElement.js │ │ │ ├── SVGElementsRenderer.js │ │ │ ├── SVGFillStyleData.js │ │ │ ├── SVGGradientFillStyleData.js │ │ │ ├── SVGGradientStrokeStyleData.js │ │ │ ├── SVGShapeData.js │ │ │ ├── SVGStrokeStyleData.js │ │ │ ├── SVGStyleData.js │ │ │ ├── SVGTransformData.js │ │ │ ├── ShapeElement.js │ │ │ ├── ShapeGroupData.js │ │ │ └── ShapeTransformManager.js │ └── svgElements │ │ ├── SVGBaseElement.js │ │ ├── SVGCompElement.js │ │ ├── SVGEffects.js │ │ ├── SVGShapeElement.js │ │ ├── SVGTextElement.js │ │ └── effects │ │ ├── SVGDropShadowEffect.js │ │ ├── SVGFillFilter.js │ │ ├── SVGGaussianBlurEffect.js │ │ ├── SVGMatte3Effect.js │ │ ├── SVGProLevelsFilter.js │ │ ├── SVGStrokeEffect.js │ │ ├── SVGTintEffect.js │ │ └── SVGTritoneFilter.js │ ├── main.js │ ├── module.js │ ├── renderers │ ├── BaseRenderer.js │ └── CanvasRenderer.js │ └── utils │ ├── BaseEvent.js │ ├── DataManager.js │ ├── FontManager.js │ ├── PropertyFactory.js │ ├── TransformProperty.js │ ├── asset_loader.js │ ├── bez.js │ ├── common.js │ ├── expressions │ ├── CompInterface.js │ ├── EffectInterface.js │ ├── ExpressionManager.js │ ├── ExpressionPropertyDecorator.js │ ├── ExpressionTextPropertyDecorator.js │ ├── ExpressionValue.js │ ├── ExpressionValueFactory.js │ ├── Expressions.js │ ├── LayerInterface.js │ ├── MaskInterface.js │ ├── ProjectInterface.js │ ├── ShapeInterface.js │ ├── TextInterface.js │ ├── TextSelectorPropertyDecorator.js │ ├── TransformInterface.js │ └── expressionHelpers.js │ ├── featureSupport.js │ ├── filters.js │ ├── functionExtensions.js │ ├── helpers │ ├── arrays.js │ ├── blendModes.js │ ├── dynamicProperties.js │ ├── html_elements.js │ └── svg_elements.js │ ├── imagePreloader.js │ ├── pooling │ ├── bezier_length_pool.js │ ├── point_pool.js │ ├── pool_factory.js │ ├── pooling.js │ ├── segments_length_pool.js │ ├── shapeCollection_pool.js │ └── shape_pool.js │ ├── shapes │ ├── DashProperty.js │ ├── GradientProperty.js │ ├── MouseModifier.js │ ├── RepeaterModifier.js │ ├── RoundCornersModifier.js │ ├── ShapeCollection.js │ ├── ShapeModifiers.js │ ├── ShapePath.js │ ├── ShapeProperty.js │ ├── TrimModifier.js │ └── shapePathBuilder.js │ └── text │ ├── LetterProps.js │ ├── TextAnimatorDataProperty.js │ ├── TextAnimatorProperty.js │ ├── TextProperty.js │ └── TextSelectorProperty.js └── tasks ├── build.js └── watch.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | player/exports/ 3 | player/tests/ 4 | node_modules/ 5 | node_modules/ 6 | demo/__output 7 | tests/ 8 | esprima/ 9 | bodymovinCert.p12 10 | ZXPSignCmd.exe 11 | signer.bat 12 | commands.txt 13 | debug.txt 14 | package-lock.json 15 | .DS_Store -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | player/exports/ 3 | player/tests/ 4 | node_modules/ 5 | tests/ 6 | demo/ 7 | esprima/ 8 | bodymovinCert.p12 9 | ZXPSignCmd.exe 10 | signer.bat 11 | gifs/ 12 | build/extension/ 13 | projects/ 14 | player/ 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "printWidth": 140, 4 | "singleQuote": true, 5 | "jsxBracketSameLinte": true 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Bodymovin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lottie for Node.js 2 | 3 | Lottie is a AE render library for Node.js that parses [Adobe After Effects](http://www.adobe.com/products/aftereffects.html) animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on web. 4 | 5 | Lottie-node is an API for runnig Lottie with the canvas renderer in Node.js, with the help of node-canvas. This is intended for rendering Lottie animations to images or video. 6 | 7 | # documentation 8 | 9 | Lottie-node is transplanted from lottie-web, so its api is exactly the same as lottie-web. 10 | View documentation, FAQ, help, examples, and more at [lottie-web](http://airbnb.io/lottie/#/web). 11 | 12 | ![Example4](./gifs/demo.gif) 13 | 14 | # Installation 15 | 16 | ```bash 17 | # with npm 18 | npm install lottie-nodejs 19 | ``` 20 | 21 | ### Install node-canvas 22 | 23 | Oh, I don't have a built-in node-canvas library by default, you can import it externally and pass it in. This design is mainly for use in conjunction with FFCreator. 24 | 25 | # UseAge 26 | 27 | - Import lottie-nodejs and node-canvas libraries. 28 | - Set up Canvas class for lottie-nodejs. 29 | - Create a Canvas instance for rendering. 30 | - Lottie loads the animation file and initializes it. 31 | - Use timer to render lottie framed animation. 32 | - Render and save the image to the local, or other operations. 33 | 34 | ```javascript 35 | // 1. Import lottie-nodejs and node-canvas libraries 36 | const lottie = require('lottie-nodejs'); 37 | const { Canvas, Image } = require('canvas'); 38 | 39 | // 2. Set up Canvas class for lottie-nodejs 40 | lottie.setCanvas({ 41 | Canvas, 42 | Image, 43 | }); 44 | 45 | // 3. Create a Canvas instance for rendering 46 | const canvas = new Canvas(500, 500); 47 | 48 | // 4. Lottie loads the animation file and initializes it 49 | const anim = lottie.loadAnimation({ 50 | container: canvas, 51 | loop: false, 52 | path: path.join(__dirname, './assets/data.json'), 53 | // animationData: data 54 | }); 55 | 56 | // 5. Use timer to render lottie framed animation 57 | setInterval(() => { 58 | anim.render(); 59 | 60 | // 6. Render and save the image to the local, or other operations 61 | const buffer = canvas.toBuffer('image/png'); 62 | const file = path.join(__dirname, `./output/imgs/${index++}.png`); 63 | fs.outputFile(file, buffer); 64 | }, 1000 / 30); 65 | ``` 66 | 67 | #### Of course you can use any api of lottie-web. 68 | 69 | ```javascript 70 | anim.goToAndStop(25, true); 71 | anim.onEnterFrame(...); 72 | ``` 73 | 74 | #### Replace placeholder images and text, etc. 75 | 76 | - Modify the Text in the lottie json data. 77 | 78 | ```javascript 79 | anim.replaceText('_xxx_', 'hello world'); 80 | ``` 81 | 82 | - Modify the Image in the lottie json data. 83 | 84 | ```javascript 85 | // param: id, newpath 86 | anim.replaceAsset(17, path.join(__dirname, 'xx.jpg')); 87 | ``` 88 | 89 | - Use lottie-api for more advanced modifications. [https://github.com/bodymovin/lottie-api](https://github.com/bodymovin/lottie-api) 90 | 91 | ```javascript 92 | const elements = anim.getApi().getKeyPath('comp1,textnode'); 93 | elements.getElements()[0].setText('hahahahah!'); 94 | 95 | // or 96 | const elements = anim.findElements('comp1,textnode'); 97 | elements[0].setText('hahahahah!'); 98 | ``` 99 | 100 | 101 | # Development 102 | 103 | Clone the project and install related dependencies 104 | 105 | ```shell 106 | git clone https://github.com/drawcall/lottie-node.git 107 | ``` 108 | 109 | #### You can run the demo to try out the project. 110 | 111 | 1. Modify the demo/index.js file and modify the values of i and j to view the demo. 112 | 113 | ```javascript 114 | // i from 1 to 4 [1-4] 115 | const i = 2; // floder 116 | // j from 1 to 20 [1-20] 117 | const j = 9; // file 118 | const num = 50; 119 | const delta = 33 * 4; 120 | ``` 121 | 122 | 2. Run the demo script. 123 | 124 | ```shell 125 | npm run demo 126 | ``` 127 | 128 | #### Run the lottie-web effect as a comparison 129 | 130 | 1. Install the `serve` package globally 131 | 132 | ```shell 133 | npm i -g serve 134 | ``` 135 | 136 | 2. Execute serve and view the corresponding demo html 137 | > modify the values of i and j to view the demo 138 | 139 | http://localhost:xxxx/demo/test/?i=2&j=9 140 | 141 | ## License 142 | 143 | [MIT License](https://opensource.org/licenses/MIT) 144 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs-extra'); 3 | const lottie = require('../build/lottie_canvas.js'); 4 | const { Canvas, Image } = require('canvas'); 5 | 6 | const i = 1; // floder 7 | const j = 0; // file 8 | const num = 50; 9 | const delta = 33 * 4; 10 | 11 | let id = 0; 12 | let index = 0; 13 | let canvas, anim, now; 14 | 15 | const saveType = 'image/png'; 16 | const file = i == 4 ? `test/data${i}/d${j}/data.json` : `test/data${i}/d${j}.json`; 17 | 18 | const removeFiles = () => { 19 | fs.remove(path.join(__dirname, './__output')); 20 | }; 21 | 22 | const intLottie = () => { 23 | canvas = new Canvas(500, 500); 24 | lottie.setCanvas({ 25 | Canvas, 26 | Image, 27 | }); 28 | 29 | anim = lottie.loadAnimation( 30 | { 31 | container: canvas, // the dom element that will contain the animation 32 | renderer: 'canvas', 33 | loop: false, 34 | path: path.join(__dirname, file), // the path to the animation json 35 | }, 36 | false 37 | ); 38 | 39 | testReplaceImage(); 40 | anim.loadNow(); 41 | 42 | const dir = path.join(__dirname, '__output'); 43 | fs.ensureDir(dir); 44 | 45 | anim.goToAndStop(1, true); 46 | id = setInterval(renderFrame, 1000 / 15, dir); 47 | }; 48 | 49 | const testReplaceImage = () => { 50 | if (i === 4 && j === 4) { 51 | const img1 = path.join(__dirname, './test/data4/image/img1.png'); 52 | const img2 = path.join(__dirname, './test/data4/image/img2.png'); 53 | anim.replaceAsset('image_1', img1); 54 | anim.replaceAsset('image_6', img2); 55 | } 56 | }; 57 | 58 | const renderFrame = (dir) => { 59 | if (index >= num) { 60 | clearInterval(id); 61 | index = 0; 62 | return; 63 | } 64 | 65 | anim.render(delta); 66 | now = Date.now(); 67 | const buffer = canvas.toBuffer(saveType); 68 | const file = path.join(dir, `${index++}.png`); 69 | console.log(`${index} save success `, file, Date.now() - now); 70 | fs.outputFile(file, buffer); 71 | }; 72 | 73 | removeFiles(); 74 | intLottie(); 75 | -------------------------------------------------------------------------------- /demo/test/data1/d7.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.10","fr":30,"ip":0,"op":60,"w":300,"h":300,"nm":"合成 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":150,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.892],"y":[0.018]},"n":["0p833_0p833_0p892_0p018"],"t":0,"s":[150],"e":[376]},{"i":{"x":[0],"y":[1.358]},"o":{"x":[0.167],"y":[0.167]},"n":["0_1p358_0p167_0p167"],"t":20,"s":[376],"e":[372.992]},{"i":{"x":[0.235],"y":[0.996]},"o":{"x":[0.041],"y":[0.004]},"n":["0p235_0p996_0p041_0p004"],"t":21,"s":[372.992],"e":[148.502]},{"i":{"x":[0.843],"y":[1]},"o":{"x":[0.682],"y":[-0.004]},"n":["0p843_1_0p682_-0p004"],"t":32,"s":[148.502],"e":[374.849]},{"i":{"x":[0.133],"y":[0.98]},"o":{"x":[0.092],"y":[0]},"n":["0p133_0p98_0p092_0"],"t":44,"s":[374.849],"e":[146.562]},{"t":59}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[59.023,59.023],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":20,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":21,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":44,"s":[100],"e":[0]},{"t":45}],"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":20,"s":[0.123996128755,0.95642562567,0.998207720588,1],"e":[1,0.272212028503,0.561320543289,1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":21,"s":[1,0.272212028503,0.561320543289,1],"e":[1,0.272212028503,0.561320543289,1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":44,"s":[1,0.272212028503,0.561320543289,1],"e":[0.1254902035,0.956862747669,1,1]},{"t":45}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-3.723,-111.227],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[{"tm":60,"cm":"1","dr":0}]} -------------------------------------------------------------------------------- /demo/test/data2/d14.json: -------------------------------------------------------------------------------- 1 | {"v":"4.11.1","fr":60,"ip":0,"op":124,"w":1920,"h":1080,"nm":"Comp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":1790,"ix":10},"p":{"a":0,"k":[972,552,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[102.75,-25.75],[0,0],[0,0]],"o":[[-72.433,18.152],[0,0],[0,0]],"v":[[-80.5,-287.5],[-14,-38],[17.25,-257.75]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0.949019610882,0.749019622803,0.031372550875,1],"e":[0.635294139385,0.854901969433,0.262745112181,1]},{"t":119}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[6.047,-8.406],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"rp","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[1],"e":[11]},{"t":119}],"ix":1},"o":{"a":0,"k":-1,"ix":2},"m":1,"ix":2,"tr":{"ty":"tr","p":{"a":0,"k":[-2,-1],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[99,99],"ix":3},"r":{"a":0,"k":396,"ix":4},"so":{"a":0,"k":100,"ix":5},"eo":{"a":0,"k":100,"ix":6},"nm":"Transform"},"nm":"Repeater 1","mn":"ADBE Vector Filter - Repeater","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[930.836,501,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[637,637],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0.965931355953,0.907860040665,0.69948643446,1],"e":[0.85221362114,0.959757983685,0.669772267342,1]},{"t":119}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[29.164,39],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[700,700],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0.949111521244,0.748911082745,0.030822843313,1],"e":[0.635294139385,0.854901969433,0.262745112181,1]},{"t":119}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[29.164,39],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":123,"st":0,"bm":0}]} -------------------------------------------------------------------------------- /demo/test/data2/d17.json: -------------------------------------------------------------------------------- 1 | {"v":"4.6.10","fr":29,"ip":0,"op":105,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[100],"e":[0]},{"t":60.0000024438501}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[200,200,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[30,30,100],"e":[100,100,100]},{"t":60.0000024438501}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[331.973,331.973]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.479,0.174],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.263,119.263],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":15,"s":[100],"e":[0]},{"t":75.0000030548126}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[200,200,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":15,"s":[30,30,100],"e":[100,100,100]},{"t":75.0000030548126}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[331.973,331.973]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.479,0.174],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.263,119.263],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":30,"s":[100],"e":[0]},{"t":90.0000036657751}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[200,200,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":30,"s":[30,30,100],"e":[100,100,100]},{"t":90.0000036657751}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[331.973,331.973]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.479,0.174],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.263,119.263],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 4","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":45,"s":[100],"e":[0]},{"t":105.000004276738}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[200,200,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":45,"s":[30,30,100],"e":[100,100,100]},{"t":105.000004276738}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[331.973,331.973]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0.479,0.174],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.263,119.263],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":900,"st":0,"bm":0,"sr":1}]} -------------------------------------------------------------------------------- /demo/test/data2/d22.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": "5.9.1", 3 | "fr": 29.9700012207031, 4 | "ip": 0, 5 | "op": 150.000006109625, 6 | "w": 400, 7 | "h": 400, 8 | "nm": "Comp 1", 9 | "ddd": 0, 10 | "assets": [], 11 | "layers": [ 12 | { 13 | "ddd": 0, 14 | "ind": 1, 15 | "ty": 4, 16 | "nm": "Shape Layer 1", 17 | "sr": 1, 18 | "ks": { 19 | "o": { "a": 0, "k": 100, "ix": 11 }, 20 | "r": { 21 | "a": 1, 22 | "k": [ 23 | { 24 | "i": { "x": [0.833], "y": [0.833] }, 25 | "o": { "x": [0.167], "y": [0.167] }, 26 | "t": 0, 27 | "s": [0] 28 | }, 29 | { "t": 149.000006068894, "s": [485] } 30 | ], 31 | "ix": 10 32 | }, 33 | "p": { 34 | "a": 1, 35 | "k": [ 36 | { 37 | "i": { "x": 0.833, "y": 0.833 }, 38 | "o": { "x": 0.167, "y": 0.167 }, 39 | "t": 0, 40 | "s": [107, 211, 0], 41 | "to": [29.833, 0, 0], 42 | "ti": [-29.833, 0, 0] 43 | }, 44 | { "t": 149.000006068894, "s": [286, 211, 0] } 45 | ], 46 | "ix": 2, 47 | "l": 2 48 | }, 49 | "a": { "a": 0, "k": [0, 0, 0], "ix": 1, "l": 2 }, 50 | "s": { "a": 0, "k": [100, 100, 100], "ix": 6, "l": 2 } 51 | }, 52 | "ao": 0, 53 | "shapes": [ 54 | { 55 | "ty": "gr", 56 | "it": [ 57 | { 58 | "ty": "rc", 59 | "d": 1, 60 | "s": { "a": 0, "k": [111.331, 111.331], "ix": 2 }, 61 | "p": { "a": 0, "k": [0, 0], "ix": 3 }, 62 | "r": { "a": 0, "k": 0, "ix": 4 }, 63 | "nm": "Rectangle Path 1", 64 | "mn": "ADBE Vector Shape - Rect", 65 | "hd": false 66 | }, 67 | { 68 | "ty": "st", 69 | "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 3 }, 70 | "o": { "a": 0, "k": 100, "ix": 4 }, 71 | "w": { "a": 0, "k": 2, "ix": 5 }, 72 | "lc": 1, 73 | "lj": 1, 74 | "ml": 4, 75 | "bm": 0, 76 | "nm": "Stroke 1", 77 | "mn": "ADBE Vector Graphic - Stroke", 78 | "hd": false 79 | }, 80 | { 81 | "ty": "fl", 82 | "c": { "a": 0, "k": [1, 0, 0, 1], "ix": 4 }, 83 | "o": { "a": 0, "k": 100, "ix": 5 }, 84 | "r": 1, 85 | "bm": 0, 86 | "nm": "Fill 1", 87 | "mn": "ADBE Vector Graphic - Fill", 88 | "hd": false 89 | }, 90 | { 91 | "ty": "tr", 92 | "p": { "a": 0, "k": [-51.335, -57.335], "ix": 2 }, 93 | "a": { "a": 0, "k": [0, 0], "ix": 1 }, 94 | "s": { "a": 0, "k": [100, 100], "ix": 3 }, 95 | "r": { "a": 0, "k": 0, "ix": 6 }, 96 | "o": { "a": 0, "k": 100, "ix": 7 }, 97 | "sk": { "a": 0, "k": 0, "ix": 4 }, 98 | "sa": { "a": 0, "k": 0, "ix": 5 }, 99 | "nm": "Transform" 100 | } 101 | ], 102 | "nm": "Rectangle 1", 103 | "np": 3, 104 | "cix": 2, 105 | "bm": 0, 106 | "ix": 1, 107 | "mn": "ADBE Vector Group", 108 | "hd": false 109 | } 110 | ], 111 | "ip": 0, 112 | "op": 150.000006109625, 113 | "st": 0, 114 | "bm": 0 115 | } 116 | ], 117 | "markers": [] 118 | } 119 | -------------------------------------------------------------------------------- /demo/test/data2/d5.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": "5.4.3", 3 | "fr": 30, 4 | "ip": 0, 5 | "op": 264, 6 | "w": 250, 7 | "h": 250, 8 | "nm": "x", 9 | "ddd": 0, 10 | "assets": [], 11 | "layers": [ 12 | { 13 | "ddd": 0, 14 | "ind": 1, 15 | "ty": 4, 16 | "nm": "Ball", 17 | "sr": 1, 18 | "ks": { 19 | "o": { "a": 0, "k": 100 }, 20 | "r": { "a": 0, "k": 0.1 }, 21 | "p": { "a": 0, "k": [125, 220, 0] }, 22 | "a": { "a": 0, "k": [125, 193, 0] }, 23 | "s": { "a": 0, "k": [150, 120, 100] } 24 | }, 25 | "ao": 0, 26 | "shapes": [ 27 | { 28 | "ty": "gr", 29 | "it": [ 30 | { 31 | "ind": 0, 32 | "ty": "sh", 33 | "ix": 1, 34 | "ks": { 35 | "a": 1, 36 | "k": [ 37 | { 38 | "i": { "x": 0.667, "y": 1 }, 39 | "o": { "x": 0.333, "y": 0 }, 40 | "n": "0p667_1_0p333_0", 41 | "t": 217, 42 | "s": [ 43 | { 44 | "i": [ 45 | [-15, -15], 46 | [15, -15], 47 | [15, 15], 48 | [-15, 15] 49 | ], 50 | "o": [ 51 | [-15, -15], 52 | [15, -15], 53 | [15, 15], 54 | [-15, 15] 55 | ], 56 | "v": [ 57 | [-15, -15], 58 | [15, -15], 59 | [15, 15], 60 | [-15, 15] 61 | ], 62 | "c": true 63 | } 64 | ] 65 | }, 66 | { "t": 221 } 67 | ], 68 | "ix": 2 69 | }, 70 | "nm": "Path 1", 71 | "mn": "ADBE Vector Shape - Group", 72 | "hd": false 73 | }, 74 | { 75 | "ty": "fl", 76 | "c": { "a": 0, "k": [1, 0, 1, 1], "ix": 4 }, 77 | "o": { "a": 0, "k": 100, "ix": 1 }, 78 | "r": 1, 79 | "nm": "Fill 1", 80 | "mn": "ADBE Vector Graphic - Fill", 81 | "hd": false 82 | }, 83 | { 84 | "ty": "tr", 85 | "p": { 86 | "a": 1, 87 | "k": [ 88 | { 89 | "i": { "x": 0.667, "y": 1 }, 90 | "o": { "x": 0.333, "y": 0 }, 91 | "n": "0p667_1_0p333_0", 92 | "t": 31, 93 | "s": [125, 58.9], 94 | "e": [125, 193.4], 95 | "to": [2.0, 22.1], 96 | "ti": [0, 0.005] 97 | }, 98 | { 99 | "i": { "x": 0.667, "y": 1 }, 100 | "o": { "x": 0.333, "y": 0 }, 101 | "n": "0p667_1_0p333_0", 102 | "t": 51, 103 | "s": [125, 193.4], 104 | "e": [125, 58.857], 105 | "to": [0, -0.1], 106 | "ti": [2.1, -0.1] 107 | } 108 | ], 109 | "ix": 2 110 | }, 111 | "a": { "a": 0, "k": [0, 25], "ix": 1 }, 112 | 113 | 114 | "s": { 115 | "a": 1, 116 | "k": [ 117 | { 118 | "i": { "x": [0.833, 0.833], "y": [1, 1] }, 119 | "o": { "x": [0.167, 0.167], "y": [0, 0] }, 120 | "n": ["0p833_1_0p167_0", "0p833_1_0p167_0"], 121 | "t": 0, 122 | "s": [0.0, 0.0] 123 | }, 124 | { 125 | "i": { "x": [0.833, 0.833], "y": [1, 1] }, 126 | "o": { "x": [0.167, 0.167], "y": [0, 0] }, 127 | "n": ["0p833_1_0p167_0", "0p833_1_0p167_0"], 128 | "t": 20, 129 | "s": [295, 80] 130 | } 131 | ], 132 | "ix": 3 133 | }, 134 | 135 | 136 | "o": { "a": 0, "k": 100, "ix": 7 }, 137 | "nm": "Transform" 138 | } 139 | ], 140 | "nm": "Group 2", 141 | "np": 2, 142 | "cix": 2, 143 | "ix": 1, 144 | "mn": "ADBE Vector Group", 145 | "hd": false 146 | } 147 | ], 148 | "ip": 0, 149 | "op": 264, 150 | "st": 0, 151 | "bm": 0 152 | } 153 | ] 154 | } 155 | -------------------------------------------------------------------------------- /demo/test/data2/d7.json: -------------------------------------------------------------------------------- 1 | {"v":"4.10.1","fr":60,"ip":0,"op":120,"w":500,"h":500,"nm":"合成 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[243.25,217.75,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[65,1.5],[-14,63],[-51.5,16]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.885],"y":[0.441]},"o":{"x":[0.167],"y":[0.111]},"n":["0p885_0p441_0p167_0p111"],"t":58,"s":[100],"e":[0]},{"t":78}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.956450760365,0.968276500702,0.977676033974,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":2,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sy":[{"ty":0,"nm":"描边","c":{"a":0,"k":[1,0,0,1],"ix":2},"s":{"a":0,"k":5.7,"ix":3}}],"shapes":[{"d":3,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":40,"s":[240,240],"e":[0,0]},{"t":60}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.655],"y":[3.556]},"o":{"x":[0.318],"y":[-1.77]},"n":["0p655_3p556_0p318_-1p77"],"t":-14,"s":[100],"e":[100]},{"i":{"x":[0.755],"y":[0.569]},"o":{"x":[0.365],"y":[0.058]},"n":["0p755_0p569_0p365_0p058"],"t":0,"s":[100],"e":[0]},{"t":30}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,1,0.501960754395,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.799],"y":[0.936]},"o":{"x":[0.21],"y":[0.675]},"n":["0p799_0p936_0p21_0p675"],"t":0,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0],"y":[0]},"n":["0p833_1_0_0"],"t":30,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":35,"s":[100],"e":[0]},{"t":55}],"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"形状图层 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.606,0.606],"y":[0.969,0.969]},"o":{"x":[0.03,0.03],"y":[0.331,0.331]},"n":["0p606_0p969_0p03_0p331","0p606_0p969_0p03_0p331"],"t":35,"s":[0,0],"e":[260,260]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]},"n":["0p833_1_0_0","0p833_1_0_0"],"t":55,"s":[260,260],"e":[230,230]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0"],"t":58,"s":[230,230],"e":[240,240]},{"t":62}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,1,0.501960754395,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.733],"y":[0.928]},"o":{"x":[0.219],"y":[0.788]},"n":["0p733_0p928_0p219_0p788"],"t":35,"s":[0],"e":[100]},{"t":55}],"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":120,"st":0,"bm":0}]} -------------------------------------------------------------------------------- /demo/test/data3/d1.json: -------------------------------------------------------------------------------- 1 | { 2 | "v": "5.4.4", 3 | "fr": 30, 4 | "ip": 0, 5 | "op": 90, 6 | "w": 178, 7 | "h": 100, 8 | "nm": "comp1", 9 | "ddd": 1, 10 | "assets": [{ "id": "image_0", "w": 610, "h": 697, "u": "images/", "p": "img_0.png", "e": 0 }], 11 | "fonts": { 12 | "list": [ 13 | { 14 | "origin": 0, 15 | "fPath": "", 16 | "fClass": "", 17 | "fFamily": "Fixedsys", 18 | "fWeight": "", 19 | "fStyle": "Regular", 20 | "fName": "Fixedsys", 21 | "ascent": 100 22 | } 23 | ] 24 | }, 25 | "layers": [ 26 | { 27 | "ddd": 1, 28 | "ind": 1, 29 | "ty": 5, 30 | "nm": "result#DMNC_TXT", 31 | "ln": "DMNC_TXT", 32 | "sr": 1, 33 | "ks": { 34 | "o": { 35 | "a": 1, 36 | "k": [{ "i": { "x": [0.833], "y": [0.833] }, "o": { "x": [0.167], "y": [0.167] }, "t": 62, "s": [10], "e": [100] }, { "t": 83 }], 37 | "ix": 11 38 | }, 39 | "rx": { "a": 0, "k": 0, "ix": 8 }, 40 | "ry": { "a": 0, "k": 0, "ix": 9 }, 41 | "rz": { "a": 0, "k": 0, "ix": 10 }, 42 | "or": { "a": 0, "k": [0, 0, 0], "ix": 7 }, 43 | "p": { "a": 0, "k": [71, 62.75, 0], "ix": 2 }, 44 | "a": { "a": 0, "k": [0, 0, 0], "ix": 1 }, 45 | "s": { "a": 0, "k": [37.269, 43.875, 100], "ix": 6 } 46 | }, 47 | "ao": 0, 48 | "t": { 49 | "d": { 50 | "k": [ 51 | { "s": { "s": 36, "f": "Fixedsys", "t": "¥金额", "j": 0, "tr": 0, "lh": 43.2, "ls": 0, "fc": [0.922, 0.922, 0.922] }, "t": 0 } 52 | ] 53 | }, 54 | "p": {}, 55 | "m": { "g": 1, "a": { "a": 0, "k": [0, 0], "ix": 2 } }, 56 | "a": [] 57 | }, 58 | "ip": 63, 59 | "op": 90, 60 | "st": 0, 61 | "bm": 0 62 | }, 63 | { 64 | "ddd": 1, 65 | "ind": 2, 66 | "ty": 2, 67 | "nm": "redbag", 68 | "refId": "image_0", 69 | "sr": 1, 70 | "ks": { 71 | "o": { "a": 0, "k": 100, "ix": 11 }, 72 | "rx": { "a": 0, "k": 0, "ix": 8 }, 73 | "ry": { 74 | "a": 1, 75 | "k": [{ "i": { "x": [0.833], "y": [0.833] }, "o": { "x": [0.167], "y": [0.167] }, "t": 50, "s": [0], "e": [360] }, { "t": 60 }], 76 | "ix": 9 77 | }, 78 | "rz": { "a": 0, "k": 0, "ix": 10 }, 79 | "or": { "a": 0, "k": [0, 0, 0], "ix": 7 }, 80 | "p": { "a": 0, "k": [89.838, 43.698, 0], "ix": 2 }, 81 | "a": { "a": 0, "k": [305, 348.5, 0], "ix": 1 }, 82 | "s": { 83 | "a": 1, 84 | "k": [ 85 | { 86 | "i": { "x": [0.833, 0.833, 0.833], "y": [0.833, 0.833, 0.833] }, 87 | "o": { "x": [0.167, 0.167, 0.167], "y": [0.167, 0.167, 0.167] }, 88 | "t": -24, 89 | "s": [2.364, 2.363, 100], 90 | "e": [13.052, 13.052, 100] 91 | }, 92 | { "t": 50 } 93 | ], 94 | "ix": 6 95 | } 96 | }, 97 | "ao": 0, 98 | "ip": 0, 99 | "op": 90, 100 | "st": 0, 101 | "bm": 0 102 | } 103 | ], 104 | "markers": [] 105 | } 106 | -------------------------------------------------------------------------------- /demo/test/data3/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data3/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_1.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_2.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_3.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_4.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_5.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_6.png -------------------------------------------------------------------------------- /demo/test/data4/d1/images/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d1/images/img_7.png -------------------------------------------------------------------------------- /demo/test/data4/d2/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d2/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d2/images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d2/images/img_1.png -------------------------------------------------------------------------------- /demo/test/data4/d2/images/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d2/images/img_2.png -------------------------------------------------------------------------------- /demo/test/data4/d2/images/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d2/images/img_3.png -------------------------------------------------------------------------------- /demo/test/data4/d2/images/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d2/images/img_4.png -------------------------------------------------------------------------------- /demo/test/data4/d3/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d3/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d3/images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d3/images/img_1.png -------------------------------------------------------------------------------- /demo/test/data4/d3/images/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d3/images/img_2.png -------------------------------------------------------------------------------- /demo/test/data4/d3/images/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d3/images/img_3.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_1.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_10.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_11.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_2.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_3.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_4.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_5.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_6.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_7.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_8.png -------------------------------------------------------------------------------- /demo/test/data4/d4/images/img_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d4/images/img_9.png -------------------------------------------------------------------------------- /demo/test/data4/d5/data.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.10","fr":48,"ip":0,"op":18,"w":750,"h":1334,"nm":"标题","ddd":0,"assets":[{"id":"image_0","w":505,"h":226,"u":"images/","p":"img_0.png"},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":2,"nm":"1-slogan.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[252.5,113,0],"ix":2},"a":{"a":0,"k":[252.5,113,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":480,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":4,"ty":0,"nm":"1-slogan.png 合成 1","cl":"png","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":2,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":260,"s":[100],"e":[0]},{"t":274}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":2,"s":[-10],"e":[-3.077]},{"t":18}],"ix":10},"p":{"a":0,"k":[274,458,0],"ix":2},"a":{"a":0,"k":[212.5,209,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":2,"s":[60,60,100],"e":[105,105,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_1_0p333_0"],"t":18,"s":[105,105,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":260,"s":[100,100,100],"e":[60,60,100]},{"t":278}],"ix":6}},"ao":0,"w":505,"h":226,"ip":0,"op":27,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /demo/test/data4/d5/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d5/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d6/data.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.10","fr":48,"ip":0,"op":18,"w":750,"h":1334,"nm":"标题","ddd":0,"assets":[{"id":"image_0","w":505,"h":226,"u":"images/","p":"img_0.png"},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":2,"nm":"2-slogan.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[252.5,113,0],"ix":2},"a":{"a":0,"k":[252.5,113,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":480,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":3,"ty":0,"nm":"2-slogan.png 合成 1","cl":"png","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":2,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":262,"s":[100],"e":[0]},{"t":276}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":2,"s":[-10],"e":[-3.077]},{"t":18}],"ix":10},"p":{"a":0,"k":[277,463,0],"ix":2},"a":{"a":0,"k":[214.5,213,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":2,"s":[60,60,100],"e":[105,105,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_1_0p333_0"],"t":18,"s":[105,105,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":262,"s":[100,100,100],"e":[60,60,100]},{"t":280}],"ix":6}},"ao":0,"w":505,"h":226,"ip":0,"op":27,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /demo/test/data4/d6/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d6/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d7/data.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.10","fr":48,"ip":0,"op":18,"w":750,"h":1334,"nm":"标题","ddd":0,"assets":[{"id":"image_0","w":505,"h":226,"u":"images/","p":"img_0.png"},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":2,"nm":"3-slogan.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[252.5,113,0],"ix":2},"a":{"a":0,"k":[252.5,113,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":2000,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":2,"ty":0,"nm":"3-slogan.png 合成 1","cl":"png","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":2,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":262,"s":[100],"e":[0]},{"t":276}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":2,"s":[-10],"e":[-3.077]},{"t":18}],"ix":10},"p":{"a":0,"k":[275,459,0],"ix":2},"a":{"a":0,"k":[212.5,209,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":2,"s":[60,60,100],"e":[105,105,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_1_0p333_0"],"t":18,"s":[105,105,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":262,"s":[100,100,100],"e":[60,60,100]},{"t":280}],"ix":6}},"ao":0,"w":505,"h":226,"ip":0,"op":27,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /demo/test/data4/d7/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d7/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/d8/data.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.10","fr":48,"ip":0,"op":18,"w":750,"h":1334,"nm":"标题","ddd":0,"assets":[{"id":"image_0","w":505,"h":226,"u":"images/","p":"img_0.png"},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":2,"nm":"4-slogan.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[252.5,113,0],"ix":2},"a":{"a":0,"k":[252.5,113,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":2000,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"4-slogan.png 合成 2","cl":"png","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":2,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":262,"s":[100],"e":[0]},{"t":276}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":2,"s":[-10],"e":[-3.077]},{"t":18}],"ix":10},"p":{"a":0,"k":[282,464,0],"ix":2},"a":{"a":0,"k":[220.166,215.85,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":2,"s":[60,60,100],"e":[105,105,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_1_0p333_0"],"t":18,"s":[105,105,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":262,"s":[100,100,100],"e":[60,60,100]},{"t":280}],"ix":6}},"ao":0,"w":505,"h":226,"ip":0,"op":78,"st":0,"bm":0}],"markers":[]} -------------------------------------------------------------------------------- /demo/test/data4/d8/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/d8/images/img_0.png -------------------------------------------------------------------------------- /demo/test/data4/image/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/image/img1.png -------------------------------------------------------------------------------- /demo/test/data4/image/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/demo/test/data4/image/img2.png -------------------------------------------------------------------------------- /demo/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /gifs/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawcall/lottie-node/732d036dbea48171b3b0ef96580c6e06df181b98/gifs/demo.gif -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export type AnimationDirection = 1 | -1; 2 | export type AnimationSegment = [number, number]; 3 | export type AnimationEventName = 'enterFrame' | 'loopComplete' | 'complete' | 'segmentStart' | 'destroy' | 'config_ready' | 'data_ready' | 'DOMLoaded' | 'error'; 4 | export type AnimationEventCallback = (args: T) => void; 5 | 6 | export type AnimationItem = { 7 | play(): void; 8 | stop(): void; 9 | pause(): void; 10 | resize(): void; 11 | setLocationHref(href: string): void; 12 | setSpeed(speed: number): void; 13 | goToAndPlay(value: number, isFrame?: boolean): void; 14 | goToAndStop(value: number, isFrame?: boolean): void; 15 | setDirection(direction: AnimationDirection): void; 16 | playSegments(segments: AnimationSegment | AnimationSegment[], forceFlag?: boolean): void; 17 | setSubframe(useSubFrames: boolean): void; 18 | destroy(): void; 19 | getDuration(inFrames?: boolean): number; 20 | triggerEvent(name: AnimationEventName, args: T): void; 21 | addEventListener(name: AnimationEventName, callback: AnimationEventCallback): void; 22 | removeEventListener(name: AnimationEventName, callback: AnimationEventCallback): void; 23 | } 24 | 25 | export type BaseRendererConfig = { 26 | imagePreserveAspectRatio?: string; 27 | className?: string; 28 | }; 29 | 30 | export type SVGRendererConfig = BaseRendererConfig & { 31 | title?: string; 32 | description?: string; 33 | preserveAspectRatio?: string; 34 | progressiveLoad?: boolean; 35 | hideOnTransparent?: boolean; 36 | viewBoxOnly?: boolean; 37 | viewBoxSize?: string; 38 | focusable?: boolean; 39 | }; 40 | 41 | export type CanvasRendererConfig = BaseRendererConfig & { 42 | clearCanvas?: boolean; 43 | context?: CanvasRenderingContext2D; 44 | progressiveLoad?: boolean; 45 | preserveAspectRatio?: string; 46 | }; 47 | 48 | export type HTMLRendererConfig = BaseRendererConfig & { 49 | hideOnTransparent?: boolean; 50 | }; 51 | 52 | export type AnimationConfig = { 53 | container: Element; 54 | renderer?: 'svg' | 'canvas' | 'html'; 55 | loop?: boolean | number; 56 | autoplay?: boolean; 57 | name?: string; 58 | rendererSettings?: SVGRendererConfig | CanvasRendererConfig | HTMLRendererConfig; 59 | } 60 | 61 | export type AnimationConfigWithPath = AnimationConfig & { 62 | path?: string; 63 | } 64 | 65 | export type AnimationConfigWithData = AnimationConfig & { 66 | animationData?: any; 67 | } 68 | 69 | type LottiePlayer = { 70 | play(name?: string): void; 71 | stop(name?: string): void; 72 | setSpeed(speed: number, name?: string): void; 73 | setDirection(direction: AnimationDirection, name?: string): void; 74 | searchAnimations(animationData?: any, standalone?: boolean, renderer?: string): void; 75 | loadAnimation(params: AnimationConfigWithPath | AnimationConfigWithData): AnimationItem; 76 | destroy(name?: string): void; 77 | registerAnimation(element: Element, animationData?: any): void; 78 | setQuality(quality: string | number): void; 79 | }; 80 | 81 | declare const Lottie: LottiePlayer; 82 | 83 | export default Lottie; 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lottie-nodejs", 3 | "version": "5.5.101", 4 | "description": "Lottie is a AE render library for Node.js", 5 | "main": "./build/lottie_canvas.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/drawcall/lottie-node" 9 | }, 10 | "scripts": { 11 | "build": "node tasks/build.js", 12 | "demo": "node demo/", 13 | "watch": "node tasks/watch.js" 14 | }, 15 | "keywords": [ 16 | "animation", 17 | "canvas", 18 | "after effects", 19 | "plugin", 20 | "export" 21 | ], 22 | "devDependencies": { 23 | "canvas": "^2.9.1", 24 | "fs-extra": "^10.0.1", 25 | "cheerio": "^1.0.0-rc.2", 26 | "watch": "^1.0.2" 27 | }, 28 | "types": "./index.d.ts", 29 | "license": "MIT", 30 | "dependencies": { 31 | "lottie-api": "^1.0.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /player/js/3rd_party/BezierEaser.js: -------------------------------------------------------------------------------- 1 | var BezierFactory = (function () { 2 | /** 3 | * BezierEasing - use bezier curve for transition easing function 4 | * by Gaëtan Renaudeau 2014 - 2015 – MIT License 5 | * 6 | * Credits: is based on Firefox's nsSMILKeySpline.cpp 7 | * Usage: 8 | * var spline = BezierEasing([ 0.25, 0.1, 0.25, 1.0 ]) 9 | * spline.get(x) => returns the easing value | x must be in [0, 1] range 10 | * 11 | */ 12 | 13 | var ob = {}; 14 | ob.getBezierEasing = getBezierEasing; 15 | var beziers = {}; 16 | 17 | function getBezierEasing(a, b, c, d, nm) { 18 | var str = nm || ('bez_' + a + '_' + b + '_' + c + '_' + d).replace(/\./g, 'p'); 19 | if (beziers[str]) { 20 | return beziers[str]; 21 | } 22 | var bezEasing = new BezierEasing([a, b, c, d]); 23 | beziers[str] = bezEasing; 24 | return bezEasing; 25 | } 26 | 27 | // These values are established by empiricism with tests (tradeoff: performance VS precision) 28 | var NEWTON_ITERATIONS = 4; 29 | var NEWTON_MIN_SLOPE = 0.001; 30 | var SUBDIVISION_PRECISION = 0.0000001; 31 | var SUBDIVISION_MAX_ITERATIONS = 10; 32 | 33 | var kSplineTableSize = 11; 34 | var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); 35 | 36 | var float32ArraySupported = typeof Float32Array === 'function'; 37 | 38 | function A(aA1, aA2) { 39 | return 1.0 - 3.0 * aA2 + 3.0 * aA1; 40 | } 41 | function B(aA1, aA2) { 42 | return 3.0 * aA2 - 6.0 * aA1; 43 | } 44 | function C(aA1) { 45 | return 3.0 * aA1; 46 | } 47 | 48 | // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. 49 | function calcBezier(aT, aA1, aA2) { 50 | return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; 51 | } 52 | 53 | // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. 54 | function getSlope(aT, aA1, aA2) { 55 | return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); 56 | } 57 | 58 | function binarySubdivide(aX, aA, aB, mX1, mX2) { 59 | var currentX, 60 | currentT, 61 | i = 0; 62 | do { 63 | currentT = aA + (aB - aA) / 2.0; 64 | currentX = calcBezier(currentT, mX1, mX2) - aX; 65 | if (currentX > 0.0) { 66 | aB = currentT; 67 | } else { 68 | aA = currentT; 69 | } 70 | } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); 71 | return currentT; 72 | } 73 | 74 | function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) { 75 | for (var i = 0; i < NEWTON_ITERATIONS; ++i) { 76 | var currentSlope = getSlope(aGuessT, mX1, mX2); 77 | if (currentSlope === 0.0) return aGuessT; 78 | var currentX = calcBezier(aGuessT, mX1, mX2) - aX; 79 | aGuessT -= currentX / currentSlope; 80 | } 81 | return aGuessT; 82 | } 83 | 84 | /** 85 | * points is an array of [ mX1, mY1, mX2, mY2 ] 86 | */ 87 | function BezierEasing(points) { 88 | this._p = points; 89 | this._mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); 90 | this._precomputed = false; 91 | 92 | this.get = this.get.bind(this); 93 | } 94 | 95 | BezierEasing.prototype = { 96 | get: function (x) { 97 | var mX1 = this._p[0], 98 | mY1 = this._p[1], 99 | mX2 = this._p[2], 100 | mY2 = this._p[3]; 101 | if (!this._precomputed) this._precompute(); 102 | if (mX1 === mY1 && mX2 === mY2) return x; // linear 103 | // Because JavaScript number are imprecise, we should guarantee the extremes are right. 104 | if (x === 0) return 0; 105 | if (x === 1) return 1; 106 | return calcBezier(this._getTForX(x), mY1, mY2); 107 | }, 108 | 109 | // Private part 110 | 111 | _precompute: function () { 112 | var mX1 = this._p[0], 113 | mY1 = this._p[1], 114 | mX2 = this._p[2], 115 | mY2 = this._p[3]; 116 | this._precomputed = true; 117 | if (mX1 !== mY1 || mX2 !== mY2) this._calcSampleValues(); 118 | }, 119 | 120 | _calcSampleValues: function () { 121 | var mX1 = this._p[0], 122 | mX2 = this._p[2]; 123 | for (var i = 0; i < kSplineTableSize; ++i) { 124 | this._mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); 125 | } 126 | }, 127 | 128 | /** 129 | * getTForX chose the fastest heuristic to determine the percentage value precisely from a given X projection. 130 | */ 131 | _getTForX: function (aX) { 132 | var mX1 = this._p[0], 133 | mX2 = this._p[2], 134 | mSampleValues = this._mSampleValues; 135 | 136 | var intervalStart = 0.0; 137 | var currentSample = 1; 138 | var lastSample = kSplineTableSize - 1; 139 | 140 | for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) { 141 | intervalStart += kSampleStepSize; 142 | } 143 | --currentSample; 144 | 145 | // Interpolate to provide an initial guess for t 146 | var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]); 147 | var guessForT = intervalStart + dist * kSampleStepSize; 148 | 149 | var initialSlope = getSlope(guessForT, mX1, mX2); 150 | if (initialSlope >= NEWTON_MIN_SLOPE) { 151 | return newtonRaphsonIterate(aX, guessForT, mX1, mX2); 152 | } else if (initialSlope === 0.0) { 153 | return guessForT; 154 | } else { 155 | return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); 156 | } 157 | }, 158 | }; 159 | 160 | return ob; 161 | })(); 162 | -------------------------------------------------------------------------------- /player/js/EffectsManager.js: -------------------------------------------------------------------------------- 1 | function EffectsManager(data, element) { 2 | var effects = data.ef || []; 3 | this.effectElements = []; 4 | var i, 5 | len = effects.length; 6 | var effectItem; 7 | for (i = 0; i < len; i++) { 8 | effectItem = new GroupEffect(effects[i], element); 9 | this.effectElements.push(effectItem); 10 | } 11 | } 12 | 13 | function GroupEffect(data, element) { 14 | this.init(data, element); 15 | } 16 | 17 | extendPrototype([DynamicPropertyContainer], GroupEffect); 18 | 19 | GroupEffect.prototype.getValue = GroupEffect.prototype.iterateDynamicProperties; 20 | 21 | GroupEffect.prototype.init = function (data, element) { 22 | this.data = data; 23 | this.effectElements = []; 24 | this.initDynamicPropertyContainer(element); 25 | var i, 26 | len = this.data.ef.length; 27 | var eff, 28 | effects = this.data.ef; 29 | for (i = 0; i < len; i += 1) { 30 | eff = null; 31 | switch (effects[i].ty) { 32 | case 0: 33 | eff = new SliderEffect(effects[i], element, this); 34 | break; 35 | case 1: 36 | eff = new AngleEffect(effects[i], element, this); 37 | break; 38 | case 2: 39 | eff = new ColorEffect(effects[i], element, this); 40 | break; 41 | case 3: 42 | eff = new PointEffect(effects[i], element, this); 43 | break; 44 | case 4: 45 | case 7: 46 | eff = new CheckboxEffect(effects[i], element, this); 47 | break; 48 | case 10: 49 | eff = new LayerIndexEffect(effects[i], element, this); 50 | break; 51 | case 11: 52 | eff = new MaskIndexEffect(effects[i], element, this); 53 | break; 54 | case 5: 55 | eff = new EffectsManager(effects[i], element, this); 56 | break; 57 | //case 6: 58 | default: 59 | eff = new NoValueEffect(effects[i], element, this); 60 | break; 61 | } 62 | if (eff) { 63 | this.effectElements.push(eff); 64 | } 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /player/js/animation/AnimationManager.js: -------------------------------------------------------------------------------- 1 | var animationManager = (function () { 2 | var moduleOb = {}; 3 | var registeredAnimations = []; 4 | var initTime = 0; 5 | var len = 0; 6 | var playingAnimationsNum = 0; 7 | var _stopped = true; 8 | var _isFrozen = false; 9 | 10 | function removeElement(ev) { 11 | var i = 0; 12 | var animItem = ev.target; 13 | while (i < len) { 14 | if (registeredAnimations[i].animation === animItem) { 15 | registeredAnimations.splice(i, 1); 16 | i -= 1; 17 | len -= 1; 18 | if (!animItem.isPaused) { 19 | subtractPlayingCount(); 20 | } 21 | } 22 | i += 1; 23 | } 24 | } 25 | 26 | function getRegisteredAnimations() { 27 | var i, 28 | len = registeredAnimations.length; 29 | var animations = []; 30 | for (i = 0; i < len; i += 1) { 31 | animations.push(registeredAnimations[i].animation); 32 | } 33 | return animations; 34 | } 35 | 36 | function addPlayingCount() { 37 | playingAnimationsNum += 1; 38 | activate(); 39 | } 40 | 41 | function subtractPlayingCount() { 42 | playingAnimationsNum -= 1; 43 | } 44 | 45 | function setupAnimation(animItem, element) { 46 | animItem.addEventListener('destroy', removeElement); 47 | animItem.addEventListener('_active', addPlayingCount); 48 | animItem.addEventListener('_idle', subtractPlayingCount); 49 | registeredAnimations.push({ elem: element, animation: animItem }); 50 | len += 1; 51 | } 52 | 53 | function loadAnimation(params, isLoadNow = true) { 54 | var animItem = new AnimationItem(); 55 | setupAnimation(animItem, null); 56 | animItem.isLoadNow = isLoadNow; 57 | animItem.setParams(params); 58 | 59 | return animItem; 60 | } 61 | 62 | function setSpeed(val, animation) { 63 | var i; 64 | for (i = 0; i < len; i += 1) { 65 | registeredAnimations[i].animation.setSpeed(val, animation); 66 | } 67 | } 68 | 69 | function setDirection(val, animation) { 70 | var i; 71 | for (i = 0; i < len; i += 1) { 72 | registeredAnimations[i].animation.setDirection(val, animation); 73 | } 74 | } 75 | 76 | function play(animation) { 77 | var i; 78 | for (i = 0; i < len; i += 1) { 79 | registeredAnimations[i].animation.play(animation); 80 | } 81 | } 82 | function resume(nowTime) { 83 | var elapsedTime = nowTime - initTime; 84 | var i; 85 | for (i = 0; i < len; i += 1) { 86 | registeredAnimations[i].animation.advanceTime(elapsedTime); 87 | } 88 | initTime = nowTime; 89 | if (playingAnimationsNum && !_isFrozen) { 90 | global.requestAnimationFrame(resume); 91 | } else { 92 | _stopped = true; 93 | } 94 | } 95 | 96 | function first(nowTime) { 97 | initTime = nowTime; 98 | global.requestAnimationFrame(resume); 99 | } 100 | 101 | function pause(animation) { 102 | var i; 103 | for (i = 0; i < len; i += 1) { 104 | registeredAnimations[i].animation.pause(animation); 105 | } 106 | } 107 | 108 | function goToAndStop(value, isFrame, animation) { 109 | var i; 110 | for (i = 0; i < len; i += 1) { 111 | registeredAnimations[i].animation.goToAndStop(value, isFrame, animation); 112 | } 113 | } 114 | 115 | function stop(animation) { 116 | var i; 117 | for (i = 0; i < len; i += 1) { 118 | registeredAnimations[i].animation.stop(animation); 119 | } 120 | } 121 | 122 | function togglePause(animation) { 123 | var i; 124 | for (i = 0; i < len; i += 1) { 125 | registeredAnimations[i].animation.togglePause(animation); 126 | } 127 | } 128 | 129 | function destroy(animation) { 130 | var i; 131 | for (i = len - 1; i >= 0; i -= 1) { 132 | registeredAnimations[i].animation.destroy(animation); 133 | } 134 | } 135 | 136 | function resize() { 137 | var i; 138 | for (i = 0; i < len; i += 1) { 139 | registeredAnimations[i].animation.resize(); 140 | } 141 | } 142 | 143 | function activate() { 144 | if (!_isFrozen && playingAnimationsNum) { 145 | if (_stopped) { 146 | //global.requestAnimationFrame(first); 147 | _stopped = false; 148 | } 149 | } 150 | } 151 | 152 | function freeze() { 153 | _isFrozen = true; 154 | } 155 | 156 | function unfreeze() { 157 | _isFrozen = false; 158 | activate(); 159 | } 160 | 161 | moduleOb.loadAnimation = loadAnimation; 162 | moduleOb.setSpeed = setSpeed; 163 | moduleOb.setDirection = setDirection; 164 | moduleOb.play = play; 165 | moduleOb.pause = pause; 166 | moduleOb.stop = stop; 167 | moduleOb.togglePause = togglePause; 168 | moduleOb.resize = resize; 169 | //moduleOb.start = start; 170 | moduleOb.goToAndStop = goToAndStop; 171 | moduleOb.destroy = destroy; 172 | moduleOb.freeze = freeze; 173 | moduleOb.unfreeze = unfreeze; 174 | moduleOb.getRegisteredAnimations = getRegisteredAnimations; 175 | return moduleOb; 176 | })(); 177 | -------------------------------------------------------------------------------- /player/js/effects/EffectsManagerPlaceholder.js: -------------------------------------------------------------------------------- 1 | function EffectsManager(){} -------------------------------------------------------------------------------- /player/js/effects/SliderEffect.js: -------------------------------------------------------------------------------- 1 | function SliderEffect(data, elem, container) { 2 | this.p = PropertyFactory.getProp(elem, data.v, 0, 0, container); 3 | } 4 | function AngleEffect(data, elem, container) { 5 | this.p = PropertyFactory.getProp(elem, data.v, 0, 0, container); 6 | } 7 | function ColorEffect(data, elem, container) { 8 | this.p = PropertyFactory.getProp(elem, data.v, 1, 0, container); 9 | } 10 | function PointEffect(data, elem, container) { 11 | this.p = PropertyFactory.getProp(elem, data.v, 1, 0, container); 12 | } 13 | function LayerIndexEffect(data, elem, container) { 14 | this.p = PropertyFactory.getProp(elem, data.v, 0, 0, container); 15 | } 16 | function MaskIndexEffect(data, elem, container) { 17 | this.p = PropertyFactory.getProp(elem, data.v, 0, 0, container); 18 | } 19 | function CheckboxEffect(data, elem, container) { 20 | this.p = PropertyFactory.getProp(elem, data.v, 0, 0, container); 21 | } 22 | function NoValueEffect() { 23 | this.p = {}; 24 | } 25 | -------------------------------------------------------------------------------- /player/js/elements/BaseElement.js: -------------------------------------------------------------------------------- 1 | function BaseElement() {} 2 | 3 | BaseElement.prototype = { 4 | checkMasks: function () { 5 | if (!this.data.hasMask) { 6 | return false; 7 | } 8 | var i = 0, 9 | len = this.data.masksProperties.length; 10 | while (i < len) { 11 | if (this.data.masksProperties[i].mode !== 'n' && this.data.masksProperties[i].cl !== false) { 12 | return true; 13 | } 14 | i += 1; 15 | } 16 | return false; 17 | }, 18 | 19 | initExpressions: function () { 20 | this.layerInterface = LayerExpressionInterface(this); 21 | if (this.data.hasMask && this.maskManager) { 22 | this.layerInterface.registerMaskInterface(this.maskManager); 23 | } 24 | var effectsInterface = EffectsExpressionInterface.createEffectsInterface(this, this.layerInterface); 25 | this.layerInterface.registerEffectsInterface(effectsInterface); 26 | 27 | if (this.data.ty === 0 || this.data.xt) { 28 | this.compInterface = CompExpressionInterface(this); 29 | } else if (this.data.ty === 4) { 30 | this.layerInterface.shapeInterface = ShapeExpressionInterface(this.shapesData, this.itemsData, this.layerInterface); 31 | this.layerInterface.content = this.layerInterface.shapeInterface; 32 | } else if (this.data.ty === 5) { 33 | this.layerInterface.textInterface = TextExpressionInterface(this); 34 | this.layerInterface.text = this.layerInterface.textInterface; 35 | } 36 | }, 37 | 38 | setBlendMode: function () { 39 | var blendModeValue = getBlendMode(this.data.bm); 40 | var elem = this.baseElement || this.layerElement; 41 | 42 | elem.style['mix-blend-mode'] = blendModeValue; 43 | }, 44 | 45 | initBaseData: function (data, globalData, comp) { 46 | this.globalData = globalData; 47 | this.comp = comp; 48 | this.data = data; 49 | this.layerId = createElementID(); 50 | 51 | //Stretch factor for old animations missing this property. 52 | if (!this.data.sr) { 53 | this.data.sr = 1; 54 | } 55 | // effects manager 56 | this.effectsManager = new EffectsManager(this.data, this, this.dynamicProperties); 57 | }, 58 | getType: function () { 59 | return this.type; 60 | }, 61 | sourceRectAtTime: function () {}, 62 | }; 63 | -------------------------------------------------------------------------------- /player/js/elements/BaseTextElement.js: -------------------------------------------------------------------------------- 1 | var BaseTextElement = function (){ 2 | }; 3 | 4 | -------------------------------------------------------------------------------- /player/js/elements/CompElement.js: -------------------------------------------------------------------------------- 1 | function ICompElement() {} 2 | 3 | extendPrototype([BaseElement, TransformElement, HierarchyElement, FrameElement, RenderableDOMElement], ICompElement); 4 | 5 | ICompElement.prototype.initElement = function (data, globalData, comp) { 6 | this.initFrame(); 7 | this.initBaseData(data, globalData, comp); 8 | this.initTransform(data, globalData, comp); 9 | this.initRenderable(); 10 | this.initHierarchy(); 11 | this.initRendererElement(); 12 | this.createContainerElements(); 13 | this.createRenderableComponents(); 14 | if (this.data.xt || !globalData.progressiveLoad) { 15 | this.buildAllItems(); 16 | } 17 | 18 | this.hide(); 19 | }; 20 | 21 | ICompElement.prototype.prepareFrame = function (num) { 22 | this._mdf = false; 23 | this.prepareRenderableFrame(num); 24 | this.prepareProperties(num, this.isInRange); 25 | 26 | if (!this.isInRange && !this.data.xt) return; 27 | 28 | if (!this.tm._placeholder) { 29 | var timeRemapped = this.tm.v; 30 | if (timeRemapped === this.data.op) { 31 | timeRemapped = this.data.op - 1; 32 | } 33 | this.renderedFrame = timeRemapped; 34 | } else { 35 | this.renderedFrame = num / this.data.sr; 36 | } 37 | 38 | var i, 39 | len = this.elements.length; 40 | 41 | if (!this.completeLayers) { 42 | this.checkLayers(this.renderedFrame); 43 | } 44 | 45 | // 由于表达式彼此之间的连接方式,此迭代需要向后进行 46 | for (i = len - 1; i >= 0; i -= 1) { 47 | if (this.completeLayers || this.elements[i]) { 48 | this.elements[i].prepareFrame(this.renderedFrame - this.layers[i].st); 49 | if (this.elements[i]._mdf) { 50 | this._mdf = true; 51 | } 52 | } 53 | } 54 | }; 55 | 56 | ICompElement.prototype.renderInnerContent = function () { 57 | var i, 58 | len = this.layers.length; 59 | for (i = 0; i < len; i += 1) { 60 | if (this.completeLayers || this.elements[i]) { 61 | this.elements[i].renderFrame(); 62 | } 63 | } 64 | }; 65 | 66 | ICompElement.prototype.setElements = function (elems) { 67 | this.elements = elems; 68 | }; 69 | 70 | ICompElement.prototype.getElements = function () { 71 | return this.elements; 72 | }; 73 | 74 | ICompElement.prototype.destroyElements = function () { 75 | var i, 76 | len = this.layers.length; 77 | for (i = 0; i < len; i += 1) { 78 | if (this.elements[i]) { 79 | this.elements[i].destroy(); 80 | } 81 | } 82 | }; 83 | 84 | ICompElement.prototype.destroy = function () { 85 | this.destroyElements(); 86 | this.destroyBaseElement(); 87 | }; 88 | -------------------------------------------------------------------------------- /player/js/elements/ImageElement.js: -------------------------------------------------------------------------------- 1 | function IImageElement(data, globalData, comp) { 2 | this.assetData = globalData.getAssetData(data.refId); 3 | this.initElement(data, globalData, comp); 4 | this.sourceRect = { top: 0, left: 0, width: this.assetData.w, height: this.assetData.h }; 5 | } 6 | 7 | extendPrototype([BaseElement, TransformElement, SVGBaseElement, HierarchyElement, FrameElement, RenderableDOMElement], IImageElement); 8 | 9 | IImageElement.prototype.createContent = function () { 10 | var assetPath = this.globalData.getAssetsPath(this.assetData); 11 | 12 | this.innerElem = createTag('image'); 13 | this.innerElem.width = this.assetData.w; 14 | this.innerElem.height = this.assetData.h; 15 | this.layerElement.appendChild(this.innerElem); 16 | }; 17 | 18 | IImageElement.prototype.sourceRectAtTime = function () { 19 | return this.sourceRect; 20 | }; 21 | -------------------------------------------------------------------------------- /player/js/elements/NullElement.js: -------------------------------------------------------------------------------- 1 | function NullElement(data, globalData, comp) { 2 | this.initFrame(); 3 | this.initBaseData(data, globalData, comp); 4 | this.initFrame(); 5 | this.initTransform(data, globalData, comp); 6 | this.initHierarchy(); 7 | } 8 | 9 | NullElement.prototype.prepareFrame = function (num) { 10 | this.prepareProperties(num, true); 11 | }; 12 | 13 | NullElement.prototype.renderFrame = function () {}; 14 | 15 | NullElement.prototype.getBaseElement = function () { 16 | return null; 17 | }; 18 | 19 | NullElement.prototype.destroy = function () {}; 20 | 21 | NullElement.prototype.sourceRectAtTime = function () {}; 22 | 23 | NullElement.prototype.hide = function () {}; 24 | 25 | extendPrototype([BaseElement, TransformElement, HierarchyElement, FrameElement], NullElement); 26 | -------------------------------------------------------------------------------- /player/js/elements/ShapeElement.js: -------------------------------------------------------------------------------- 1 | function IShapeElement() {} 2 | 3 | IShapeElement.prototype = { 4 | addShapeToModifiers: function (data) { 5 | var i, 6 | len = this.shapeModifiers.length; 7 | for (i = 0; i < len; i += 1) { 8 | this.shapeModifiers[i].addShape(data); 9 | } 10 | }, 11 | 12 | isShapeInAnimatedModifiers: function (data) { 13 | var i = 0, 14 | len = this.shapeModifiers.length; 15 | while (i < len) { 16 | if (this.shapeModifiers[i].isAnimatedWithShape(data)) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | }, 22 | 23 | renderModifiers: function () { 24 | if (!this.shapeModifiers.length) { 25 | return; 26 | } 27 | 28 | var i, 29 | len = this.shapes.length; 30 | for (i = 0; i < len; i += 1) { 31 | this.shapes[i].sh.reset(); 32 | } 33 | 34 | len = this.shapeModifiers.length; 35 | for (i = len - 1; i >= 0; i -= 1) { 36 | this.shapeModifiers[i].processShapes(this._isFirstFrame); 37 | } 38 | }, 39 | 40 | lcEnum: { 41 | 1: 'butt', 42 | 2: 'round', 43 | 3: 'square', 44 | }, 45 | ljEnum: { 46 | 1: 'miter', 47 | 2: 'round', 48 | 3: 'bevel', 49 | }, 50 | 51 | searchProcessedElement: function (elem) { 52 | var elements = this.processedElements; 53 | var i = 0, 54 | len = elements.length; 55 | while (i < len) { 56 | if (elements[i].elem === elem) { 57 | return elements[i].pos; 58 | } 59 | i += 1; 60 | } 61 | return 0; 62 | }, 63 | 64 | addProcessedElement: function (elem, pos) { 65 | var elements = this.processedElements; 66 | var i = elements.length; 67 | while (i) { 68 | i -= 1; 69 | if (elements[i].elem === elem) { 70 | elements[i].pos = pos; 71 | return; 72 | } 73 | } 74 | elements.push(new ProcessedElement(elem, pos)); 75 | }, 76 | 77 | prepareFrame: function (num) { 78 | this.prepareRenderableFrame(num); 79 | this.prepareProperties(num, this.isInRange); 80 | }, 81 | }; 82 | -------------------------------------------------------------------------------- /player/js/elements/SolidElement.js: -------------------------------------------------------------------------------- 1 | function ISolidElement(data, globalData, comp) { 2 | this.initElement(data, globalData, comp); 3 | } 4 | extendPrototype([IImageElement], ISolidElement); 5 | 6 | ISolidElement.prototype.createContent = function () { 7 | var rect = createNS('rect'); 8 | rect.setAttribute('width', this.data.sw); 9 | rect.setAttribute('height', this.data.sh); 10 | rect.setAttribute('fill', this.data.sc); 11 | this.layerElement.appendChild(rect); 12 | }; 13 | -------------------------------------------------------------------------------- /player/js/elements/TextElement.js: -------------------------------------------------------------------------------- 1 | function ITextElement() {} 2 | 3 | ITextElement.prototype.initElement = function (data, globalData, comp) { 4 | this.lettersChangedFlag = true; 5 | this.initFrame(); 6 | this.initBaseData(data, globalData, comp); 7 | this.textProperty = new TextProperty(this, data.t, this.dynamicProperties); 8 | this.textAnimator = new TextAnimatorProperty(data.t, this.renderType, this); 9 | this.initTransform(data, globalData, comp); 10 | this.initHierarchy(); 11 | this.initRenderable(); 12 | this.initRendererElement(); 13 | this.createContainerElements(); 14 | this.createRenderableComponents(); 15 | this.createContent(); 16 | this.hide(); 17 | this.textAnimator.searchProperties(this.dynamicProperties); 18 | }; 19 | 20 | ITextElement.prototype.prepareFrame = function (num) { 21 | this._mdf = false; 22 | this.prepareRenderableFrame(num); 23 | this.prepareProperties(num, this.isInRange); 24 | if (this.textProperty._mdf || this.textProperty._isFirstFrame) { 25 | this.buildNewText(); 26 | this.textProperty._isFirstFrame = false; 27 | this.textProperty._mdf = false; 28 | } 29 | }; 30 | 31 | ITextElement.prototype.createPathShape = function (matrixHelper, shapes) { 32 | var j, 33 | jLen = shapes.length; 34 | var k, kLen, pathNodes; 35 | var shapeStr = ''; 36 | for (j = 0; j < jLen; j += 1) { 37 | pathNodes = shapes[j].ks.k; 38 | shapeStr += buildShapeString(pathNodes, pathNodes.i.length, true, matrixHelper); 39 | } 40 | return shapeStr; 41 | }; 42 | 43 | ITextElement.prototype.updateDocumentData = function (newData, index) { 44 | this.textProperty.updateDocumentData(newData, index); 45 | }; 46 | 47 | ITextElement.prototype.canResizeFont = function (_canResize) { 48 | this.textProperty.canResizeFont(_canResize); 49 | }; 50 | 51 | ITextElement.prototype.setMinimumFontSize = function (_fontSize) { 52 | this.textProperty.setMinimumFontSize(_fontSize); 53 | }; 54 | 55 | ITextElement.prototype.applyTextPropertiesToMatrix = function (documentData, matrixHelper, lineNumber, xPos, yPos) { 56 | if (documentData.ps) { 57 | matrixHelper.translate(documentData.ps[0], documentData.ps[1] + documentData.ascent, 0); 58 | } 59 | matrixHelper.translate(0, -documentData.ls, 0); 60 | switch (documentData.j) { 61 | case 1: 62 | matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber]), 0, 0); 63 | break; 64 | case 2: 65 | matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber]) / 2, 0, 0); 66 | break; 67 | } 68 | matrixHelper.translate(xPos, yPos, 0); 69 | }; 70 | 71 | ITextElement.prototype.buildColor = function (colorData) { 72 | return 'rgb(' + Math.round(colorData[0] * 255) + ',' + Math.round(colorData[1] * 255) + ',' + Math.round(colorData[2] * 255) + ')'; 73 | }; 74 | 75 | ITextElement.prototype.emptyProp = new LetterProps(); 76 | 77 | ITextElement.prototype.destroy = function () {}; 78 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVBaseElement.js: -------------------------------------------------------------------------------- 1 | function CVBaseElement() {} 2 | 3 | CVBaseElement.prototype = { 4 | createElements: function () {}, 5 | initRendererElement: function () {}, 6 | createContainerElements: function () { 7 | this.canvasContext = this.globalData.canvasContext; 8 | this.renderableEffectsManager = new CVEffects(this); 9 | }, 10 | 11 | createContent: function () {}, 12 | 13 | setBlendMode: function () { 14 | var globalData = this.globalData; 15 | if (globalData.blendMode !== this.data.bm) { 16 | globalData.blendMode = this.data.bm; 17 | var blendModeValue = getBlendMode(this.data.bm); 18 | globalData.canvasContext.globalCompositeOperation = blendModeValue; 19 | } 20 | }, 21 | 22 | createRenderableComponents: function () { 23 | this.maskManager = new CVMaskElement(this.data, this); 24 | }, 25 | 26 | hideElement: function () { 27 | if (!this.hidden && (!this.isInRange || this.isTransparent)) { 28 | this.hidden = true; 29 | } 30 | }, 31 | 32 | showElement: function () { 33 | if (this.isInRange && !this.isTransparent) { 34 | this.hidden = false; 35 | this._isFirstFrame = true; 36 | this.maskManager._isFirstFrame = true; 37 | } 38 | }, 39 | 40 | renderFrame: function () { 41 | if (this.hidden || this.data.hd) { 42 | return; 43 | } 44 | 45 | this.renderTransform(); 46 | this.renderRenderable(); 47 | this.setBlendMode(); 48 | var forceRealStack = this.data.ty === 0; 49 | this.globalData.renderer.save(forceRealStack); 50 | this.globalData.renderer.ctxTransform(this.finalTransform.mat.props); 51 | this.globalData.renderer.ctxOpacity(this.finalTransform.mProp.o.v); 52 | this.renderInnerContent(); 53 | this.globalData.renderer.restore(forceRealStack); 54 | 55 | if (this.maskManager.hasMasks) { 56 | this.globalData.renderer.restore(true); 57 | } 58 | if (this._isFirstFrame) { 59 | this._isFirstFrame = false; 60 | } 61 | }, 62 | 63 | destroy: function () { 64 | this.canvasContext = null; 65 | this.data = null; 66 | this.globalData = null; 67 | this.maskManager.destroy(); 68 | }, 69 | mHelper: new Matrix(), 70 | }; 71 | CVBaseElement.prototype.hide = CVBaseElement.prototype.hideElement; 72 | CVBaseElement.prototype.show = CVBaseElement.prototype.showElement; 73 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVCompElement.js: -------------------------------------------------------------------------------- 1 | function CVCompElement(data, globalData, comp) { 2 | this.completeLayers = false; 3 | this.layers = data.layers; 4 | this.pendingElements = []; 5 | this.elements = createSizedArray(this.layers.length); 6 | this.initElement(data, globalData, comp); 7 | this.tm = data.tm ? PropertyFactory.getProp(this, data.tm, 0, globalData.frameRate, this) : { _placeholder: true }; 8 | } 9 | 10 | extendPrototype([CanvasRenderer, ICompElement, CVBaseElement], CVCompElement); 11 | 12 | CVCompElement.prototype.renderInnerContent = function () { 13 | var ctx = this.canvasContext; 14 | ctx.beginPath(); 15 | ctx.moveTo(0, 0); 16 | ctx.lineTo(this.data.w, 0); 17 | ctx.lineTo(this.data.w, this.data.h); 18 | ctx.lineTo(0, this.data.h); 19 | ctx.lineTo(0, 0); 20 | ctx.clip(); 21 | var i, 22 | len = this.layers.length; 23 | for (i = len - 1; i >= 0; i -= 1) { 24 | if (this.completeLayers || this.elements[i]) { 25 | this.elements[i].renderFrame(); 26 | } 27 | } 28 | }; 29 | 30 | CVCompElement.prototype.destroy = function () { 31 | var i, 32 | len = this.layers.length; 33 | for (i = len - 1; i >= 0; i -= 1) { 34 | if (this.elements[i]) { 35 | this.elements[i].destroy(); 36 | } 37 | } 38 | this.layers = null; 39 | this.elements = null; 40 | }; 41 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVContextData.js: -------------------------------------------------------------------------------- 1 | function CVContextData() { 2 | this.saved = []; 3 | this.cArrPos = 0; 4 | this.cTr = new Matrix(); 5 | this.cO = 1; 6 | var i, 7 | len = 15; 8 | this.savedOp = createTypedArray('float32', len); 9 | for (i = 0; i < len; i += 1) { 10 | this.saved[i] = createTypedArray('float32', 16); 11 | } 12 | 13 | this._length = len; 14 | } 15 | 16 | CVContextData.prototype.duplicate = function () { 17 | var newLength = this._length * 2; 18 | var currentSavedOp = this.savedOp; 19 | this.savedOp = createTypedArray('float32', newLength); 20 | this.savedOp.set(currentSavedOp); 21 | var i = 0; 22 | for (i = this._length; i < newLength; i += 1) { 23 | this.saved[i] = createTypedArray('float32', 16); 24 | } 25 | this._length = newLength; 26 | }; 27 | 28 | CVContextData.prototype.reset = function () { 29 | this.cArrPos = 0; 30 | this.cTr.reset(); 31 | this.cO = 1; 32 | }; 33 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVEffects.js: -------------------------------------------------------------------------------- 1 | function CVEffects() {} 2 | CVEffects.prototype.renderFrame = function () {}; 3 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVImageElement.js: -------------------------------------------------------------------------------- 1 | function CVImageElement(data, globalData, comp) { 2 | this.assetData = globalData.getAssetData(data.refId); 3 | this.img = globalData.imageLoader.getImage(this.assetData); 4 | this.initElement(data, globalData, comp); 5 | } 6 | extendPrototype([BaseElement, TransformElement, CVBaseElement, HierarchyElement, FrameElement, RenderableElement], CVImageElement); 7 | 8 | CVImageElement.prototype.initElement = SVGShapeElement.prototype.initElement; 9 | CVImageElement.prototype.prepareFrame = IImageElement.prototype.prepareFrame; 10 | 11 | CVImageElement.prototype.createContent = function () { 12 | if (this.img.width && (this.assetData.w !== this.img.width || this.assetData.h !== this.img.height)) { 13 | var canvas = createTag('canvas'); 14 | canvas.width = this.assetData.w; 15 | canvas.height = this.assetData.h; 16 | var ctx = canvas.getContext('2d'); 17 | 18 | var imgW = this.img.width; 19 | var imgH = this.img.height; 20 | var imgRel = imgW / imgH; 21 | var canvasRel = this.assetData.w / this.assetData.h; 22 | var widthCrop, heightCrop; 23 | var par = this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio; 24 | 25 | if ((imgRel > canvasRel && par === 'xMidYMid slice') || (imgRel < canvasRel && par !== 'xMidYMid slice')) { 26 | heightCrop = imgH; 27 | widthCrop = heightCrop * canvasRel; 28 | } else { 29 | widthCrop = imgW; 30 | heightCrop = widthCrop / canvasRel; 31 | } 32 | 33 | ctx.drawImage( 34 | this.img, 35 | (imgW - widthCrop) / 2, 36 | (imgH - heightCrop) / 2, 37 | widthCrop, 38 | heightCrop, 39 | 0, 40 | 0, 41 | this.assetData.w, 42 | this.assetData.h 43 | ); 44 | this.img = canvas; 45 | } 46 | }; 47 | 48 | CVImageElement.prototype.renderInnerContent = function (parentMatrix) { 49 | this.canvasContext.drawImage(this.img, 0, 0); 50 | }; 51 | 52 | CVImageElement.prototype.destroy = function () { 53 | this.img = null; 54 | }; 55 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVMaskElement.js: -------------------------------------------------------------------------------- 1 | function CVMaskElement(data, element) { 2 | this.data = data; 3 | this.element = element; 4 | this.masksProperties = this.data.masksProperties || []; 5 | this.viewData = createSizedArray(this.masksProperties.length); 6 | var i, 7 | len = this.masksProperties.length, 8 | hasMasks = false; 9 | 10 | for (i = 0; i < len; i++) { 11 | if (this.masksProperties[i].mode !== 'n') { 12 | hasMasks = true; 13 | } 14 | this.viewData[i] = ShapePropertyFactory.getShapeProp(this.element, this.masksProperties[i], 3); 15 | } 16 | this.hasMasks = hasMasks; 17 | if (hasMasks) { 18 | this.element.addRenderableComponent(this); 19 | } 20 | } 21 | 22 | CVMaskElement.prototype.renderFrame = function () { 23 | if (!this.hasMasks) return; 24 | 25 | var transform = this.element.finalTransform.mat; 26 | var ctx = this.element.canvasContext; 27 | var i, 28 | len = this.masksProperties.length; 29 | var pt, pts, data; 30 | 31 | ctx.beginPath(); 32 | for (i = 0; i < len; i++) { 33 | if (this.masksProperties[i].mode !== 'n') { 34 | if (this.masksProperties[i].inv) { 35 | ctx.moveTo(0, 0); 36 | ctx.lineTo(this.element.globalData.compSize.w, 0); 37 | ctx.lineTo(this.element.globalData.compSize.w, this.element.globalData.compSize.h); 38 | ctx.lineTo(0, this.element.globalData.compSize.h); 39 | ctx.lineTo(0, 0); 40 | } 41 | 42 | data = this.viewData[i].v; 43 | pt = transform.applyToPointArray(data.v[0][0], data.v[0][1], 0); 44 | ctx.moveTo(pt[0], pt[1]); 45 | var j, 46 | jLen = data._length; 47 | for (j = 1; j < jLen; j++) { 48 | pts = transform.applyToTriplePoints(data.o[j - 1], data.i[j], data.v[j]); 49 | ctx.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); 50 | } 51 | pts = transform.applyToTriplePoints(data.o[j - 1], data.i[0], data.v[0]); 52 | ctx.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); 53 | } 54 | } 55 | this.element.globalData.renderer.save(true); 56 | ctx.clip(); 57 | }; 58 | 59 | CVMaskElement.prototype.getMaskProperty = function (pos) { 60 | return this.viewData[pos].prop; 61 | }; 62 | 63 | CVMaskElement.prototype.destroy = function () { 64 | this.element = null; 65 | }; 66 | -------------------------------------------------------------------------------- /player/js/elements/canvasElements/CVSolidElement.js: -------------------------------------------------------------------------------- 1 | function CVSolidElement(data, globalData, comp) { 2 | this.initElement(data, globalData, comp); 3 | } 4 | extendPrototype([BaseElement, TransformElement, CVBaseElement, HierarchyElement, FrameElement, RenderableElement], CVSolidElement); 5 | 6 | CVSolidElement.prototype.initElement = SVGShapeElement.prototype.initElement; 7 | CVSolidElement.prototype.prepareFrame = IImageElement.prototype.prepareFrame; 8 | 9 | CVSolidElement.prototype.renderInnerContent = function () { 10 | var ctx = this.canvasContext; 11 | ctx.fillStyle = this.data.sc; 12 | ctx.fillRect(0, 0, this.data.sw, this.data.sh); 13 | // 14 | }; 15 | -------------------------------------------------------------------------------- /player/js/elements/helpers/FrameElement.js: -------------------------------------------------------------------------------- 1 | function FrameElement() {} 2 | 3 | FrameElement.prototype = { 4 | initFrame: function () { 5 | // 渲染 inpoint 时设置为 true 6 | this._isFirstFrame = false; 7 | // 动画属性列表 8 | this.dynamicProperties = []; 9 | // 如果图层在当前刻度中已被修改,这将是 true 10 | this._mdf = false; 11 | }, 12 | 13 | prepareProperties: function (num, isVisible) { 14 | var i, 15 | len = this.dynamicProperties.length; 16 | 17 | for (i = 0; i < len; i += 1) { 18 | if (isVisible || (this._isParent && this.dynamicProperties[i].propType === 'transform')) { 19 | this.dynamicProperties[i].getValue(); 20 | 21 | if (this.dynamicProperties[i]._mdf) { 22 | this.globalData._mdf = true; 23 | this._mdf = true; 24 | } 25 | } 26 | } 27 | }, 28 | 29 | addDynamicProperty: function (prop) { 30 | if (this.dynamicProperties.indexOf(prop) === -1) { 31 | this.dynamicProperties.push(prop); 32 | } 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /player/js/elements/helpers/HierarchyElement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Handles AE's layer parenting property. 4 | * 5 | */ 6 | 7 | function HierarchyElement(){} 8 | 9 | HierarchyElement.prototype = { 10 | /** 11 | * @function 12 | * Initializes hierarchy properties 13 | * 14 | */ 15 | initHierarchy: function() { 16 | //element's parent list 17 | this.hierarchy = []; 18 | //if element is parent of another layer _isParent will be true 19 | this._isParent = false; 20 | this.checkParenting(); 21 | }, 22 | /** 23 | * @function 24 | * Sets layer's hierarchy. 25 | * @param {array} hierarch 26 | * layer's parent list 27 | * 28 | */ 29 | setHierarchy: function(hierarchy){ 30 | this.hierarchy = hierarchy; 31 | }, 32 | /** 33 | * @function 34 | * Sets layer as parent. 35 | * 36 | */ 37 | setAsParent: function() { 38 | this._isParent = true; 39 | }, 40 | /** 41 | * @function 42 | * Searches layer's parenting chain 43 | * 44 | */ 45 | checkParenting: function(){ 46 | if (this.data.parent !== undefined){ 47 | this.comp.buildElementParenting(this, this.data.parent, []); 48 | } 49 | } 50 | }; -------------------------------------------------------------------------------- /player/js/elements/helpers/RenderableDOMElement.js: -------------------------------------------------------------------------------- 1 | function RenderableDOMElement() {} 2 | 3 | (function () { 4 | var _prototype = { 5 | initElement: function (data, globalData, comp) { 6 | this.initFrame(); 7 | this.initBaseData(data, globalData, comp); 8 | this.initTransform(data, globalData, comp); 9 | this.initHierarchy(); 10 | this.initRenderable(); 11 | this.initRendererElement(); 12 | this.createContainerElements(); 13 | this.createRenderableComponents(); 14 | this.createContent(); 15 | this.hide(); 16 | }, 17 | hide: function () { 18 | if (!this.hidden && (!this.isInRange || this.isTransparent)) { 19 | var elem = this.baseElement || this.layerElement; 20 | elem.style.display = 'none'; 21 | this.hidden = true; 22 | } 23 | }, 24 | show: function () { 25 | if (this.isInRange && !this.isTransparent) { 26 | if (!this.data.hd) { 27 | var elem = this.baseElement || this.layerElement; 28 | elem.style.display = 'block'; 29 | } 30 | this.hidden = false; 31 | this._isFirstFrame = true; 32 | } 33 | }, 34 | 35 | renderFrame: function () { 36 | //If it is exported as hidden (data.hd === true) no need to render 37 | //If it is not visible no need to render 38 | if (this.data.hd || this.hidden) { 39 | return; 40 | } 41 | this.renderTransform(); 42 | this.renderRenderable(); 43 | this.renderElement(); 44 | this.renderInnerContent(); 45 | if (this._isFirstFrame) { 46 | this._isFirstFrame = false; 47 | } 48 | }, 49 | renderInnerContent: function () {}, 50 | prepareFrame: function (num) { 51 | this._mdf = false; 52 | this.prepareRenderableFrame(num); 53 | this.prepareProperties(num, this.isInRange); 54 | this.checkTransparency(); 55 | }, 56 | destroy: function () { 57 | this.innerElem = null; 58 | this.destroyBaseElement(); 59 | }, 60 | }; 61 | extendPrototype([RenderableElement, createProxyFunction(_prototype)], RenderableDOMElement); 62 | })(); 63 | -------------------------------------------------------------------------------- /player/js/elements/helpers/RenderableElement.js: -------------------------------------------------------------------------------- 1 | function RenderableElement() {} 2 | 3 | RenderableElement.prototype = { 4 | initRenderable: function () { 5 | //layer's visibility related to inpoint and outpoint. Rename isVisible to isInRange 6 | this.isInRange = false; 7 | //layer's display state 8 | this.hidden = false; 9 | // If layer's transparency equals 0, it can be hidden 10 | this.isTransparent = false; 11 | //list of animated components 12 | this.renderableComponents = []; 13 | }, 14 | 15 | addRenderableComponent: function (component) { 16 | if (this.renderableComponents.indexOf(component) === -1) { 17 | this.renderableComponents.push(component); 18 | } 19 | }, 20 | 21 | removeRenderableComponent: function (component) { 22 | if (this.renderableComponents.indexOf(component) !== -1) { 23 | this.renderableComponents.splice(this.renderableComponents.indexOf(component), 1); 24 | } 25 | }, 26 | 27 | prepareRenderableFrame: function (num) { 28 | this.checkLayerLimits(num); 29 | }, 30 | 31 | checkTransparency: function () { 32 | if (this.finalTransform.mProp.o.v <= 0) { 33 | if (!this.isTransparent && this.globalData.renderConfig.hideOnTransparent) { 34 | this.isTransparent = true; 35 | this.hide(); 36 | } 37 | } else if (this.isTransparent) { 38 | this.isTransparent = false; 39 | this.show(); 40 | } 41 | }, 42 | 43 | checkLayerLimits: function (num) { 44 | // ip-开始帧 | st-开始时间 | op-持续帧长 45 | // [a-num-b] 46 | if (this.data.ip - this.data.st <= num && this.data.op - this.data.st > num) { 47 | if (this.isInRange !== true) { 48 | this.globalData._mdf = true; 49 | this._mdf = true; 50 | this.isInRange = true; 51 | this.show(); 52 | } 53 | } else { 54 | if (this.isInRange !== false) { 55 | this.globalData._mdf = true; 56 | this.isInRange = false; 57 | this.hide(); 58 | } 59 | } 60 | }, 61 | 62 | renderRenderable: function () { 63 | var i, 64 | len = this.renderableComponents.length; 65 | for (i = 0; i < len; i += 1) { 66 | this.renderableComponents[i].renderFrame(this._isFirstFrame); 67 | } 68 | }, 69 | 70 | sourceRectAtTime: function () { 71 | return { 72 | top: 0, 73 | left: 0, 74 | width: 100, 75 | height: 100, 76 | }; 77 | }, 78 | 79 | getLayerSize: function () { 80 | if (this.data.ty === 5) { 81 | return { w: this.data.textData.width, h: this.data.textData.height }; 82 | } else { 83 | return { w: this.data.width, h: this.data.height }; 84 | } 85 | }, 86 | }; 87 | -------------------------------------------------------------------------------- /player/js/elements/helpers/TransformElement.js: -------------------------------------------------------------------------------- 1 | function TransformElement() {} 2 | 3 | TransformElement.prototype = { 4 | initTransform: function () { 5 | this.finalTransform = { 6 | mProp: this.data.ks ? TransformPropertyFactory.getTransformProperty(this, this.data.ks, this) : { o: 0 }, 7 | _matMdf: false, 8 | _opMdf: false, 9 | mat: new Matrix(), 10 | }; 11 | if (this.data.ao) { 12 | this.finalTransform.mProp.autoOriented = true; 13 | } 14 | 15 | //TODO: check TYPE 11: Guided elements 16 | if (this.data.ty !== 11) { 17 | //this.createElements(); 18 | } 19 | }, 20 | 21 | renderTransform: function () { 22 | this.finalTransform._opMdf = this.finalTransform.mProp.o._mdf || this._isFirstFrame; 23 | this.finalTransform._matMdf = this.finalTransform.mProp._mdf || this._isFirstFrame; 24 | 25 | if (this.hierarchy) { 26 | var mat; 27 | var finalMat = this.finalTransform.mat; 28 | var i = 0, 29 | len = this.hierarchy.length; 30 | //Checking if any of the transformation matrices in the hierarchy chain has changed. 31 | if (!this.finalTransform._matMdf) { 32 | while (i < len) { 33 | if (this.hierarchy[i].finalTransform.mProp._mdf) { 34 | this.finalTransform._matMdf = true; 35 | break; 36 | } 37 | i += 1; 38 | } 39 | } 40 | 41 | if (this.finalTransform._matMdf) { 42 | mat = this.finalTransform.mProp.v.props; 43 | finalMat.cloneFromProps(mat); 44 | for (i = 0; i < len; i += 1) { 45 | mat = this.hierarchy[i].finalTransform.mProp.v.props; 46 | finalMat.transform( 47 | mat[0], 48 | mat[1], 49 | mat[2], 50 | mat[3], 51 | mat[4], 52 | mat[5], 53 | mat[6], 54 | mat[7], 55 | mat[8], 56 | mat[9], 57 | mat[10], 58 | mat[11], 59 | mat[12], 60 | mat[13], 61 | mat[14], 62 | mat[15] 63 | ); 64 | } 65 | } 66 | } 67 | }, 68 | 69 | globalToLocal: function (pt) { 70 | var transforms = []; 71 | transforms.push(this.finalTransform); 72 | var flag = true; 73 | var comp = this.comp; 74 | while (flag) { 75 | if (comp.finalTransform) { 76 | if (comp.data.hasMask) { 77 | transforms.splice(0, 0, comp.finalTransform); 78 | } 79 | comp = comp.comp; 80 | } else { 81 | flag = false; 82 | } 83 | } 84 | var i, 85 | len = transforms.length, 86 | ptNew; 87 | for (i = 0; i < len; i += 1) { 88 | ptNew = transforms[i].mat.applyToPointArray(0, 0, 0); 89 | //ptNew = transforms[i].mat.applyToPointArray(pt[0],pt[1],pt[2]); 90 | pt = [pt[0] - ptNew[0], pt[1] - ptNew[1], 0]; 91 | } 92 | return pt; 93 | }, 94 | mHelper: new Matrix(), 95 | }; 96 | -------------------------------------------------------------------------------- /player/js/elements/helpers/shapes/CVShapeData.js: -------------------------------------------------------------------------------- 1 | function CVShapeData(element, data, styles, transformsManager) { 2 | this.styledShapes = []; 3 | this.tr = [0, 0, 0, 0, 0, 0]; 4 | var ty = 4; 5 | if (data.ty == 'rc') { 6 | ty = 5; 7 | } else if (data.ty == 'el') { 8 | ty = 6; 9 | } else if (data.ty == 'sr') { 10 | ty = 7; 11 | } 12 | 13 | this.sh = ShapePropertyFactory.getShapeProp(element, data, ty, element); 14 | var i, 15 | len = styles.length, 16 | styledShape; 17 | for (i = 0; i < len; i += 1) { 18 | if (!styles[i].closed) { 19 | styledShape = { 20 | transforms: transformsManager.addTransformSequence(styles[i].transforms), 21 | trNodes: [], 22 | }; 23 | this.styledShapes.push(styledShape); 24 | styles[i].elements.push(styledShape); 25 | } 26 | } 27 | } 28 | 29 | CVShapeData.prototype.setAsAnimated = SVGShapeData.prototype.setAsAnimated; 30 | -------------------------------------------------------------------------------- /player/js/elements/helpers/shapes/ProcessedElement.js: -------------------------------------------------------------------------------- 1 | function ProcessedElement(element, position) { 2 | this.elem = element; 3 | this.pos = position; 4 | } -------------------------------------------------------------------------------- /player/js/elements/helpers/shapes/SVGFillStyleData.js: -------------------------------------------------------------------------------- 1 | function SVGFillStyleData(elem, data, styleOb){ 2 | this.initDynamicPropertyContainer(elem); 3 | this.getValue = this.iterateDynamicProperties; 4 | this.o = PropertyFactory.getProp(elem,data.o,0,0.01,this); 5 | this.c = PropertyFactory.getProp(elem,data.c,1,255,this); 6 | this.style = styleOb; 7 | } 8 | 9 | extendPrototype([DynamicPropertyContainer], SVGFillStyleData); -------------------------------------------------------------------------------- /player/js/elements/helpers/shapes/SVGGradientFillStyleData.js: -------------------------------------------------------------------------------- 1 | function SVGGradientFillStyleData(elem, data, styleOb){ 2 | this.initDynamicPropertyContainer(elem); 3 | this.getValue = this.iterateDynamicProperties; 4 | this.initGradientData(elem, data, styleOb); 5 | } 6 | 7 | SVGGradientFillStyleData.prototype.initGradientData = function(elem, data, styleOb){ 8 | this.o = PropertyFactory.getProp(elem,data.o,0,0.01,this); 9 | this.s = PropertyFactory.getProp(elem,data.s,1,null,this); 10 | this.e = PropertyFactory.getProp(elem,data.e,1,null,this); 11 | this.h = PropertyFactory.getProp(elem,data.h||{k:0},0,0.01,this); 12 | this.a = PropertyFactory.getProp(elem,data.a||{k:0},0,degToRads,this); 13 | this.g = new GradientProperty(elem,data.g,this); 14 | this.style = styleOb; 15 | this.stops = []; 16 | this.setGradientData(styleOb.pElem, data); 17 | this.setGradientOpacity(data, styleOb); 18 | this._isAnimated = !!this._isAnimated; 19 | 20 | }; 21 | 22 | SVGGradientFillStyleData.prototype.setGradientData = function(pathElement,data){ 23 | 24 | var gradientId = createElementID(); 25 | var gfill = createNS(data.t === 1 ? 'linearGradient' : 'radialGradient'); 26 | gfill.setAttribute('id',gradientId); 27 | gfill.setAttribute('spreadMethod','pad'); 28 | gfill.setAttribute('gradientUnits','userSpaceOnUse'); 29 | var stops = []; 30 | var stop, j, jLen; 31 | jLen = data.g.p*4; 32 | for(j=0;j= 0; i -= 1) { 49 | props = sequence.transforms[i].transform.mProps.v.props; 50 | sequence.finalTransform.transform( 51 | props[0], 52 | props[1], 53 | props[2], 54 | props[3], 55 | props[4], 56 | props[5], 57 | props[6], 58 | props[7], 59 | props[8], 60 | props[9], 61 | props[10], 62 | props[11], 63 | props[12], 64 | props[13], 65 | props[14], 66 | props[15] 67 | ); 68 | } 69 | } 70 | sequence._mdf = _mdf; 71 | }, 72 | 73 | processSequences: function (isFirstFrame) { 74 | var i, 75 | len = this.sequenceList.length; 76 | for (i = 0; i < len; i += 1) { 77 | this.processSequence(this.sequenceList[i], isFirstFrame); 78 | } 79 | }, 80 | 81 | getNewKey: function () { 82 | return '_' + this.transform_key_count++; 83 | }, 84 | }; 85 | -------------------------------------------------------------------------------- /player/js/elements/svgElements/SVGCompElement.js: -------------------------------------------------------------------------------- 1 | function SVGCompElement(data,globalData,comp){ 2 | this.layers = data.layers; 3 | this.supports3d = true; 4 | this.completeLayers = false; 5 | this.pendingElements = []; 6 | this.elements = this.layers ? createSizedArray(this.layers.length) : []; 7 | //this.layerElement = createNS('g'); 8 | this.initElement(data,globalData,comp); 9 | this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate,this) : {_placeholder:true}; 10 | } 11 | 12 | extendPrototype([SVGRenderer, ICompElement, SVGBaseElement], SVGCompElement); -------------------------------------------------------------------------------- /player/js/elements/svgElements/SVGEffects.js: -------------------------------------------------------------------------------- 1 | function SVGEffects(elem){ 2 | var i, len = elem.data.ef ? elem.data.ef.length : 0; 3 | var filId = createElementID(); 4 | var fil = filtersFactory.createFilter(filId); 5 | var count = 0; 6 | this.filters = []; 7 | var filterManager; 8 | for(i=0;i horizontal & vertical 23 | // 2 -> horizontal only 24 | // 3 -> vertical only 25 | // 26 | var dimensions = this.filterManager.effectElements[1].p.v; 27 | var sigmaX = (dimensions == 3) ? 0 : sigma; 28 | var sigmaY = (dimensions == 2) ? 0 : sigma; 29 | 30 | this.feGaussianBlur.setAttribute('stdDeviation', sigmaX + " " + sigmaY); 31 | 32 | // Repeat edges mapping: 33 | // 34 | // 0 -> off -> duplicate 35 | // 1 -> on -> wrap 36 | var edgeMode = (this.filterManager.effectElements[2].p.v == 1) ? 'wrap' : 'duplicate'; 37 | this.feGaussianBlur.setAttribute('edgeMode', edgeMode); 38 | } 39 | } -------------------------------------------------------------------------------- /player/js/elements/svgElements/effects/SVGMatte3Effect.js: -------------------------------------------------------------------------------- 1 | var _svgMatteSymbols = []; 2 | 3 | function SVGMatte3Effect(filterElem, filterManager, elem){ 4 | this.initialized = false; 5 | this.filterManager = filterManager; 6 | this.filterElem = filterElem; 7 | this.elem = elem; 8 | elem.matteElement = createNS('g'); 9 | elem.matteElement.appendChild(elem.layerElement); 10 | elem.matteElement.appendChild(elem.transformedElement); 11 | elem.baseElement = elem.matteElement; 12 | } 13 | 14 | SVGMatte3Effect.prototype.findSymbol = function(mask) { 15 | var i = 0, len = _svgMatteSymbols.length; 16 | while(i < len) { 17 | if(_svgMatteSymbols[i] === mask) { 18 | return _svgMatteSymbols[i]; 19 | } 20 | i += 1; 21 | } 22 | return null; 23 | }; 24 | 25 | SVGMatte3Effect.prototype.replaceInParent = function(mask, symbolId) { 26 | var parentNode = mask.layerElement.parentNode; 27 | if(!parentNode) { 28 | return; 29 | } 30 | var children = parentNode.children; 31 | var i = 0, len = children.length; 32 | while (i < len) { 33 | if (children[i] === mask.layerElement) { 34 | break; 35 | } 36 | i += 1; 37 | } 38 | var nextChild; 39 | if (i <= len - 2) { 40 | nextChild = children[i + 1]; 41 | } 42 | var useElem = createNS('use'); 43 | useElem.setAttribute('href', '#' + symbolId); 44 | if(nextChild) { 45 | parentNode.insertBefore(useElem, nextChild); 46 | } else { 47 | parentNode.appendChild(useElem); 48 | } 49 | }; 50 | 51 | SVGMatte3Effect.prototype.setElementAsMask = function(elem, mask) { 52 | if(!this.findSymbol(mask)) { 53 | var symbolId = createElementID(); 54 | var masker = createNS('mask'); 55 | masker.setAttribute('id', mask.layerId); 56 | masker.setAttribute('mask-type', 'alpha'); 57 | _svgMatteSymbols.push(mask); 58 | var defs = elem.globalData.defs; 59 | defs.appendChild(masker); 60 | var symbol = createNS('symbol'); 61 | symbol.setAttribute('id', symbolId); 62 | this.replaceInParent(mask, symbolId); 63 | symbol.appendChild(mask.layerElement); 64 | defs.appendChild(symbol); 65 | var useElem = createNS('use'); 66 | useElem.setAttribute('href', '#' + symbolId); 67 | masker.appendChild(useElem); 68 | mask.data.hd = false; 69 | mask.show(); 70 | } 71 | elem.setMatte(mask.layerId); 72 | }; 73 | 74 | SVGMatte3Effect.prototype.initialize = function() { 75 | var ind = this.filterManager.effectElements[0].p.v; 76 | var elements = this.elem.comp.elements; 77 | var i = 0, len = elements.length; 78 | while (i < len) { 79 | if (elements[i] && elements[i].data.ind === ind) { 80 | this.setElementAsMask(this.elem, elements[i]); 81 | } 82 | i += 1; 83 | } 84 | this.initialized = true; 85 | }; 86 | 87 | SVGMatte3Effect.prototype.renderFrame = function() { 88 | if(!this.initialized) { 89 | this.initialize(); 90 | } 91 | }; -------------------------------------------------------------------------------- /player/js/elements/svgElements/effects/SVGStrokeEffect.js: -------------------------------------------------------------------------------- 1 | function SVGStrokeEffect(elem, filterManager){ 2 | this.initialized = false; 3 | this.filterManager = filterManager; 4 | this.elem = elem; 5 | this.paths = []; 6 | } 7 | 8 | SVGStrokeEffect.prototype.initialize = function(){ 9 | 10 | var elemChildren = this.elem.layerElement.children || this.elem.layerElement.childNodes; 11 | var path,groupPath, i, len; 12 | if(this.filterManager.effectElements[1].p.v === 1){ 13 | len = this.elem.maskManager.masksProperties.length; 14 | i = 0; 15 | } else { 16 | i = this.filterManager.effectElements[0].p.v - 1; 17 | len = i + 1; 18 | } 19 | groupPath = createNS('g'); 20 | groupPath.setAttribute('fill','none'); 21 | groupPath.setAttribute('stroke-linecap','round'); 22 | groupPath.setAttribute('stroke-dashoffset',1); 23 | for(i;i*/ 15 | var lottiejs = {}; 16 | var _isFrozen = false; 17 | 18 | function setLocationHref(href) { 19 | locationHref = href; 20 | } 21 | 22 | function setSubframeRendering(flag) { 23 | subframeEnabled = flag; 24 | } 25 | 26 | function loadAnimation(params, isLoadNow) { 27 | return animationManager.loadAnimation(params, isLoadNow); 28 | } 29 | 30 | function setQuality(value) { 31 | if (typeof value === 'string') { 32 | switch (value) { 33 | case 'high': 34 | defaultCurveSegments = 200; 35 | break; 36 | case 'medium': 37 | defaultCurveSegments = 50; 38 | break; 39 | case 'low': 40 | defaultCurveSegments = 10; 41 | break; 42 | } 43 | } else if (!isNaN(value) && value > 1) { 44 | defaultCurveSegments = value; 45 | } 46 | if (defaultCurveSegments >= 50) { 47 | roundValues(false); 48 | } else { 49 | roundValues(true); 50 | } 51 | } 52 | 53 | function inBrowser() { 54 | return true; 55 | } 56 | 57 | function installPlugin(type, plugin) { 58 | if (type === 'expressions') { 59 | expressionsPlugin = plugin; 60 | } 61 | } 62 | 63 | function getFactory(name) { 64 | switch (name) { 65 | case 'propertyFactory': 66 | return PropertyFactory; 67 | case 'shapePropertyFactory': 68 | return ShapePropertyFactory; 69 | case 'matrix': 70 | return Matrix; 71 | } 72 | } 73 | 74 | lottiejs.canvas = null; 75 | lottiejs.setCanvas = function (canvas) { 76 | lottiejs.canvas = canvas; 77 | }; 78 | lottiejs.play = animationManager.play; 79 | lottiejs.pause = animationManager.pause; 80 | lottiejs.setLocationHref = setLocationHref; 81 | lottiejs.togglePause = animationManager.togglePause; 82 | lottiejs.setSpeed = animationManager.setSpeed; 83 | lottiejs.setDirection = animationManager.setDirection; 84 | lottiejs.stop = animationManager.stop; 85 | lottiejs.loadAnimation = loadAnimation; 86 | lottiejs.setSubframeRendering = setSubframeRendering; 87 | lottiejs.resize = animationManager.resize; 88 | lottiejs.goToAndStop = animationManager.goToAndStop; 89 | lottiejs.destroy = animationManager.destroy; 90 | lottiejs.setQuality = setQuality; 91 | lottiejs.inBrowser = inBrowser; 92 | lottiejs.installPlugin = installPlugin; 93 | lottiejs.freeze = animationManager.freeze; 94 | lottiejs.unfreeze = animationManager.unfreeze; 95 | lottiejs.getRegisteredAnimations = animationManager.getRegisteredAnimations; 96 | lottiejs.__getFactory = getFactory; 97 | lottiejs.version = '[[BM_VERSION]]'; 98 | 99 | var standalone = '__[STANDALONE]__'; 100 | var animationData = '__[ANIMATIONDATA]__'; 101 | var renderer = ''; 102 | 103 | return lottiejs; 104 | }); 105 | -------------------------------------------------------------------------------- /player/js/renderers/BaseRenderer.js: -------------------------------------------------------------------------------- 1 | function BaseRenderer() {} 2 | BaseRenderer.prototype.checkLayers = function (num) { 3 | var i, 4 | len = this.layers.length, 5 | data; 6 | this.completeLayers = true; 7 | 8 | for (i = len - 1; i >= 0; i--) { 9 | if (!this.elements[i]) { 10 | data = this.layers[i]; 11 | if (data.ip - data.st <= num - this.layers[i].st && data.op - data.st > num - this.layers[i].st) { 12 | this.buildItem(i); 13 | } 14 | } 15 | this.completeLayers = this.elements[i] ? this.completeLayers : false; 16 | } 17 | 18 | this.checkPendingElements(); 19 | }; 20 | 21 | // 2: image,图片 22 | // 0: comp,合成图层 23 | // 1: solid; 24 | // 3: null; 25 | // 4: shape,形状图层 26 | // 5: text,文字 27 | BaseRenderer.prototype.createItem = function (layer) { 28 | switch (layer.ty) { 29 | case 2: 30 | return this.createImage(layer); 31 | case 0: 32 | return this.createComp(layer); 33 | case 1: 34 | return this.createSolid(layer); 35 | case 3: 36 | return this.createNull(layer); 37 | case 4: 38 | return this.createShape(layer); 39 | case 5: 40 | return this.createText(layer); 41 | case 13: 42 | return this.createCamera(layer); 43 | } 44 | 45 | return this.createNull(layer); 46 | }; 47 | 48 | BaseRenderer.prototype.createCamera = function () { 49 | throw new Error("You're using a 3d camera. Try the html renderer."); 50 | }; 51 | 52 | BaseRenderer.prototype.buildAllItems = function () { 53 | var i, 54 | len = this.layers.length; 55 | for (i = 0; i < len; i += 1) { 56 | this.buildItem(i); 57 | } 58 | this.checkPendingElements(); 59 | }; 60 | 61 | BaseRenderer.prototype.includeLayers = function (newLayers) { 62 | this.completeLayers = false; 63 | var i, 64 | len = newLayers.length; 65 | var j, 66 | jLen = this.layers.length; 67 | for (i = 0; i < len; i += 1) { 68 | j = 0; 69 | while (j < jLen) { 70 | if (this.layers[j].id == newLayers[i].id) { 71 | this.layers[j] = newLayers[i]; 72 | break; 73 | } 74 | j += 1; 75 | } 76 | } 77 | }; 78 | 79 | BaseRenderer.prototype.setProjectInterface = function (pInterface) { 80 | this.globalData.projectInterface = pInterface; 81 | }; 82 | 83 | BaseRenderer.prototype.initItems = function () { 84 | if (!this.globalData.progressiveLoad) { 85 | this.buildAllItems(); 86 | } 87 | }; 88 | BaseRenderer.prototype.buildElementParenting = function (element, parentName, hierarchy) { 89 | var elements = this.elements; 90 | var layers = this.layers; 91 | var i = 0, 92 | len = layers.length; 93 | while (i < len) { 94 | if (layers[i].ind == parentName) { 95 | if (!elements[i] || elements[i] === true) { 96 | this.buildItem(i); 97 | this.addPendingElement(element); 98 | } else { 99 | hierarchy.push(elements[i]); 100 | elements[i].setAsParent(); 101 | if (layers[i].parent !== undefined) { 102 | this.buildElementParenting(element, layers[i].parent, hierarchy); 103 | } else { 104 | element.setHierarchy(hierarchy); 105 | } 106 | } 107 | } 108 | i += 1; 109 | } 110 | }; 111 | 112 | BaseRenderer.prototype.addPendingElement = function (element) { 113 | this.pendingElements.push(element); 114 | }; 115 | 116 | BaseRenderer.prototype.searchExtraCompositions = function (assets) { 117 | var i, 118 | len = assets.length; 119 | for (i = 0; i < len; i += 1) { 120 | if (assets[i].xt) { 121 | var comp = this.createComp(assets[i]); 122 | comp.initExpressions(); 123 | this.globalData.projectInterface.registerComposition(comp); 124 | } 125 | } 126 | }; 127 | 128 | BaseRenderer.prototype.setupGlobalData = function (animData, fontsContainer) { 129 | this.globalData.fontManager = new FontManager(); 130 | this.globalData.fontManager.addChars(animData.chars); 131 | this.globalData.fontManager.addFonts(animData.fonts, fontsContainer); 132 | this.globalData.getAssetData = this.animationItem.getAssetData.bind(this.animationItem); 133 | this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem); 134 | this.globalData.imageLoader = this.animationItem.imagePreloader; 135 | this.globalData.frameId = 0; 136 | this.globalData.frameRate = animData.fr; 137 | this.globalData.nm = animData.nm; 138 | this.globalData.compSize = { 139 | w: animData.w, 140 | h: animData.h, 141 | }; 142 | }; 143 | -------------------------------------------------------------------------------- /player/js/utils/BaseEvent.js: -------------------------------------------------------------------------------- 1 | function BaseEvent() {} 2 | BaseEvent.prototype = { 3 | triggerEvent: function (eventName, args) { 4 | if (this._cbs[eventName]) { 5 | var len = this._cbs[eventName].length; 6 | for (var i = 0; i < len; i++) { 7 | this._cbs[eventName][i](args); 8 | } 9 | } 10 | }, 11 | addEventListener: function (eventName, callback) { 12 | if (!this._cbs[eventName]) { 13 | this._cbs[eventName] = []; 14 | } 15 | this._cbs[eventName].push(callback); 16 | 17 | return function () { 18 | this.removeEventListener(eventName, callback); 19 | }.bind(this); 20 | }, 21 | removeEventListener: function (eventName, callback) { 22 | if (!callback) { 23 | this._cbs[eventName] = null; 24 | } else if (this._cbs[eventName]) { 25 | var i = 0, 26 | len = this._cbs[eventName].length; 27 | while (i < len) { 28 | if (this._cbs[eventName][i] === callback) { 29 | this._cbs[eventName].splice(i, 1); 30 | i -= 1; 31 | len -= 1; 32 | } 33 | i += 1; 34 | } 35 | if (!this._cbs[eventName].length) { 36 | this._cbs[eventName] = null; 37 | } 38 | } 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /player/js/utils/FontManager.js: -------------------------------------------------------------------------------- 1 | var FontManager = (function () { 2 | var emptyChar = { 3 | w: 0, 4 | size: 0, 5 | shapes: [], 6 | }; 7 | var combinedCharacters = []; 8 | //Hindi characters 9 | combinedCharacters = combinedCharacters.concat([ 10 | 2304, 2305, 2306, 2307, 2362, 2363, 2364, 2364, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 11 | 2380, 2381, 2382, 2383, 2387, 2388, 2389, 2390, 2391, 2402, 2403, 12 | ]); 13 | 14 | function addFonts(fontData) { 15 | if (!fontData) { 16 | this.isLoaded = true; 17 | return; 18 | } 19 | 20 | if (this.chars) { 21 | this.isLoaded = true; 22 | this.fonts = fontData.list; 23 | return; 24 | } 25 | 26 | var fontArr = fontData.list; 27 | var i; 28 | var len = fontArr.length; 29 | 30 | for (i = 0; i < len; i += 1) { 31 | fontArr[i].loaded = false; 32 | fontArr[i].monoCase = null; 33 | fontArr[i].sansCase = null; 34 | fontArr[i].loaded = true; 35 | fontArr[i].helper = null; 36 | fontArr[i].cache = {}; 37 | this.fonts.push(fontArr[i]); 38 | } 39 | 40 | this.isLoaded = true; 41 | } 42 | 43 | function addChars(chars) { 44 | if (!chars) { 45 | return; 46 | } 47 | if (!this.chars) { 48 | this.chars = []; 49 | } 50 | var i, 51 | len = chars.length; 52 | var j, 53 | jLen = this.chars.length, 54 | found; 55 | for (i = 0; i < len; i += 1) { 56 | j = 0; 57 | found = false; 58 | while (j < jLen) { 59 | if (this.chars[j].style === chars[i].style && this.chars[j].fFamily === chars[i].fFamily && this.chars[j].ch === chars[i].ch) { 60 | found = true; 61 | } 62 | j += 1; 63 | } 64 | if (!found) { 65 | this.chars.push(chars[i]); 66 | jLen += 1; 67 | } 68 | } 69 | } 70 | 71 | function getCharData(char, style, font, size) { 72 | if (!this.chars) { 73 | this.chars = []; 74 | } 75 | 76 | var i = 0, 77 | len = this.chars.length; 78 | 79 | while (i < len) { 80 | if (this.chars[i].ch === char && this.chars[i].style === style && this.chars[i].fFamily === font) { 81 | return this.chars[i]; 82 | } 83 | i += 1; 84 | } 85 | 86 | return Object.assign(emptyChar, { size, w: size }); 87 | } 88 | 89 | function measureText(char, fontName, size) { 90 | var fontData = this.getFontByName(fontName); 91 | var index = char.charCodeAt(0); 92 | 93 | if (!fontData.cache[index + 1]) { 94 | // var tHelper = fontData.helper; 95 | // if (char === ' ') { 96 | // tHelper.textContent = '|' + char + '|'; 97 | // var doubleSize = tHelper.getComputedTextLength(); 98 | // tHelper.textContent = '||'; 99 | // var singleSize = tHelper.getComputedTextLength(); 100 | // fontData.cache[index + 1] = (doubleSize - singleSize) / 100; 101 | // } else { 102 | // tHelper.textContent = char; 103 | // fontData.cache[index + 1] = tHelper.getComputedTextLength() / 100; 104 | // } 105 | fontData.cache[index + 1] = 1; 106 | } 107 | 108 | return fontData.cache[index + 1] * size; 109 | } 110 | 111 | function getFontByName(fontName) { 112 | var i = 0, 113 | len = this.fonts.length; 114 | while (i < len) { 115 | if (this.fonts[i].fName === fontName) { 116 | return this.fonts[i]; 117 | } 118 | 119 | i += 1; 120 | } 121 | 122 | return { cache: {} }; 123 | } 124 | 125 | function getCombinedCharacterCodes() { 126 | return combinedCharacters; 127 | } 128 | 129 | function loaded() { 130 | return this.isLoaded; 131 | } 132 | 133 | var Font = function () { 134 | this.fonts = []; 135 | this.chars = null; 136 | this.typekitLoaded = 0; 137 | this.isLoaded = true; 138 | }; 139 | 140 | //TODO: for now I'm adding these methods to the Class and not the prototype. Think of a better way to implement it. 141 | Font.getCombinedCharacterCodes = getCombinedCharacterCodes; 142 | Font.prototype.addChars = addChars; 143 | Font.prototype.addFonts = addFonts; 144 | Font.prototype.getCharData = getCharData; 145 | Font.prototype.getFontByName = getFontByName; 146 | Font.prototype.measureText = measureText; 147 | Font.prototype.loaded = loaded; 148 | 149 | return Font; 150 | })(); 151 | -------------------------------------------------------------------------------- /player/js/utils/asset_loader.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var assetLoader = (function () { 4 | function loadAsset(path, callback, errorCallback) { 5 | try { 6 | var data = fs.readFileSync(path, 'utf-8'); 7 | const body = JSON.parse(data); 8 | callback(body); 9 | } catch (err) { 10 | errorCallback(err); 11 | } 12 | } 13 | 14 | return { 15 | load: loadAsset, 16 | }; 17 | })(); 18 | -------------------------------------------------------------------------------- /player/js/utils/expressions/CompInterface.js: -------------------------------------------------------------------------------- 1 | var CompExpressionInterface = (function () { 2 | return function(comp) { 3 | function _thisLayerFunction(name) { 4 | var i = 0, len = comp.layers.length; 5 | while ( i < len) { 6 | if (comp.layers[i].nm === name || comp.layers[i].ind === name) { 7 | return comp.elements[i].layerInterface; 8 | } 9 | i += 1; 10 | } 11 | return null; 12 | //return {active:false}; 13 | } 14 | Object.defineProperty(_thisLayerFunction, "_name", { value: comp.data.nm }); 15 | _thisLayerFunction.layer = _thisLayerFunction; 16 | _thisLayerFunction.pixelAspect = 1; 17 | _thisLayerFunction.height = comp.data.h || comp.globalData.compSize.h; 18 | _thisLayerFunction.width = comp.data.w || comp.globalData.compSize.w; 19 | _thisLayerFunction.pixelAspect = 1; 20 | _thisLayerFunction.frameDuration = 1 / comp.globalData.frameRate; 21 | _thisLayerFunction.displayStartTime = 0; 22 | _thisLayerFunction.numLayers = comp.layers.length; 23 | return _thisLayerFunction; 24 | }; 25 | }()); -------------------------------------------------------------------------------- /player/js/utils/expressions/EffectInterface.js: -------------------------------------------------------------------------------- 1 | var EffectsExpressionInterface = (function (){ 2 | var ob = { 3 | createEffectsInterface: createEffectsInterface 4 | }; 5 | 6 | function createEffectsInterface(elem, propertyGroup){ 7 | if(elem.effectsManager){ 8 | 9 | var effectElements = []; 10 | var effectsData = elem.data.ef; 11 | var i, len = elem.effectsManager.effectElements.length; 12 | for(i=0;i 0.01){ 21 | return false; 22 | } 23 | i += 1; 24 | } 25 | return true; 26 | }; 27 | 28 | GradientProperty.prototype.checkCollapsable = function() { 29 | if (this.o.length/2 !== this.c.length/4) { 30 | return false; 31 | } 32 | if (this.data.k.k[0].s) { 33 | var i = 0, len = this.data.k.k.length; 34 | while (i < len) { 35 | if (!this.comparePoints(this.data.k.k[i].s, this.data.p)) { 36 | return false; 37 | } 38 | i += 1; 39 | } 40 | } else if(!this.comparePoints(this.data.k.k, this.data.p)) { 41 | return false; 42 | } 43 | return true; 44 | }; 45 | 46 | GradientProperty.prototype.getValue = function(forceRender){ 47 | this.prop.getValue(); 48 | this._mdf = false; 49 | this._cmdf = false; 50 | this._omdf = false; 51 | if(this.prop._mdf || forceRender){ 52 | var i, len = this.data.p*4; 53 | var mult, val; 54 | for(i=0;i= this._maxLength) { 40 | this.doubleArrayLength(); 41 | } 42 | switch(type){ 43 | case 'v': 44 | arr = this.v; 45 | break; 46 | case 'i': 47 | arr = this.i; 48 | break; 49 | case 'o': 50 | arr = this.o; 51 | break; 52 | } 53 | if(!arr[pos] || (arr[pos] && !replace)){ 54 | arr[pos] = point_pool.newElement(); 55 | } 56 | arr[pos][0] = x; 57 | arr[pos][1] = y; 58 | }; 59 | 60 | ShapePath.prototype.setTripleAt = function(vX,vY,oX,oY,iX,iY,pos, replace) { 61 | this.setXYAt(vX,vY,'v',pos, replace); 62 | this.setXYAt(oX,oY,'o',pos, replace); 63 | this.setXYAt(iX,iY,'i',pos, replace); 64 | }; 65 | 66 | ShapePath.prototype.reverse = function() { 67 | var newPath = new ShapePath(); 68 | newPath.setPathData(this.c, this._length); 69 | var vertices = this.v, outPoints = this.o, inPoints = this.i; 70 | var init = 0; 71 | if (this.c) { 72 | newPath.setTripleAt(vertices[0][0], vertices[0][1], inPoints[0][0], inPoints[0][1], outPoints[0][0], outPoints[0][1], 0, false); 73 | init = 1; 74 | } 75 | var cnt = this._length - 1; 76 | var len = this._length; 77 | 78 | var i; 79 | for (i = init; i < len; i += 1) { 80 | newPath.setTripleAt(vertices[cnt][0], vertices[cnt][1], inPoints[cnt][0], inPoints[cnt][1], outPoints[cnt][0], outPoints[cnt][1], i, false); 81 | cnt -= 1; 82 | } 83 | return newPath; 84 | }; -------------------------------------------------------------------------------- /player/js/utils/shapes/shapePathBuilder.js: -------------------------------------------------------------------------------- 1 | var buildShapeString = function(pathNodes, length, closed, mat) { 2 | if(length === 0) { 3 | return ''; 4 | } 5 | var _o = pathNodes.o; 6 | var _i = pathNodes.i; 7 | var _v = pathNodes.v; 8 | var i, shapeString = " M" + mat.applyToPointStringified(_v[0][0], _v[0][1]); 9 | for(i = 1; i < length; i += 1) { 10 | shapeString += " C" + mat.applyToPointStringified(_o[i - 1][0], _o[i - 1][1]) + " " + mat.applyToPointStringified(_i[i][0], _i[i][1]) + " " + mat.applyToPointStringified(_v[i][0], _v[i][1]); 11 | } 12 | if (closed && length) { 13 | shapeString += " C" + mat.applyToPointStringified(_o[i - 1][0], _o[i - 1][1]) + " " + mat.applyToPointStringified(_i[0][0], _i[0][1]) + " " + mat.applyToPointStringified(_v[0][0], _v[0][1]); 14 | shapeString += 'z'; 15 | } 16 | return shapeString; 17 | } -------------------------------------------------------------------------------- /player/js/utils/text/LetterProps.js: -------------------------------------------------------------------------------- 1 | function LetterProps(o, sw, sc, fc, m, p){ 2 | this.o = o; 3 | this.sw = sw; 4 | this.sc = sc; 5 | this.fc = fc; 6 | this.m = m; 7 | this.p = p; 8 | this._mdf = { 9 | o: true, 10 | sw: !!sw, 11 | sc: !!sc, 12 | fc: !!fc, 13 | m: true, 14 | p: true 15 | }; 16 | } 17 | 18 | LetterProps.prototype.update = function(o, sw, sc, fc, m, p) { 19 | this._mdf.o = false; 20 | this._mdf.sw = false; 21 | this._mdf.sc = false; 22 | this._mdf.fc = false; 23 | this._mdf.m = false; 24 | this._mdf.p = false; 25 | var updated = false; 26 | 27 | if(this.o !== o) { 28 | this.o = o; 29 | this._mdf.o = true; 30 | updated = true; 31 | } 32 | if(this.sw !== sw) { 33 | this.sw = sw; 34 | this._mdf.sw = true; 35 | updated = true; 36 | } 37 | if(this.sc !== sc) { 38 | this.sc = sc; 39 | this._mdf.sc = true; 40 | updated = true; 41 | } 42 | if(this.fc !== fc) { 43 | this.fc = fc; 44 | this._mdf.fc = true; 45 | updated = true; 46 | } 47 | if(this.m !== m) { 48 | this.m = m; 49 | this._mdf.m = true; 50 | updated = true; 51 | } 52 | if(p.length && (this.p[0] !== p[0] || this.p[1] !== p[1] || this.p[4] !== p[4] || this.p[5] !== p[5] || this.p[12] !== p[12] || this.p[13] !== p[13])) { 53 | this.p = p; 54 | this._mdf.p = true; 55 | updated = true; 56 | } 57 | return updated; 58 | }; -------------------------------------------------------------------------------- /player/js/utils/text/TextAnimatorDataProperty.js: -------------------------------------------------------------------------------- 1 | function TextAnimatorDataProperty(elem, animatorProps, container) { 2 | var defaultData = {propType:false}; 3 | var getProp = PropertyFactory.getProp; 4 | var textAnimator_animatables = animatorProps.a; 5 | this.a = { 6 | r: textAnimator_animatables.r ? getProp(elem, textAnimator_animatables.r, 0, degToRads, container) : defaultData, 7 | rx: textAnimator_animatables.rx ? getProp(elem, textAnimator_animatables.rx, 0, degToRads, container) : defaultData, 8 | ry: textAnimator_animatables.ry ? getProp(elem, textAnimator_animatables.ry, 0, degToRads, container) : defaultData, 9 | sk: textAnimator_animatables.sk ? getProp(elem, textAnimator_animatables.sk, 0, degToRads, container) : defaultData, 10 | sa: textAnimator_animatables.sa ? getProp(elem, textAnimator_animatables.sa, 0, degToRads, container) : defaultData, 11 | s: textAnimator_animatables.s ? getProp(elem, textAnimator_animatables.s, 1, 0.01, container) : defaultData, 12 | a: textAnimator_animatables.a ? getProp(elem, textAnimator_animatables.a, 1, 0, container) : defaultData, 13 | o: textAnimator_animatables.o ? getProp(elem, textAnimator_animatables.o, 0, 0.01, container) : defaultData, 14 | p: textAnimator_animatables.p ? getProp(elem,textAnimator_animatables.p, 1, 0, container) : defaultData, 15 | sw: textAnimator_animatables.sw ? getProp(elem, textAnimator_animatables.sw, 0, 0, container) : defaultData, 16 | sc: textAnimator_animatables.sc ? getProp(elem, textAnimator_animatables.sc, 1, 0, container) : defaultData, 17 | fc: textAnimator_animatables.fc ? getProp(elem, textAnimator_animatables.fc, 1, 0, container) : defaultData, 18 | fh: textAnimator_animatables.fh ? getProp(elem, textAnimator_animatables.fh, 0, 0, container) : defaultData, 19 | fs: textAnimator_animatables.fs ? getProp(elem, textAnimator_animatables.fs, 0, 0.01, container) : defaultData, 20 | fb: textAnimator_animatables.fb ? getProp(elem, textAnimator_animatables.fb, 0, 0.01, container) : defaultData, 21 | t: textAnimator_animatables.t ? getProp(elem, textAnimator_animatables.t, 0, 0, container) : defaultData 22 | }; 23 | 24 | this.s = TextSelectorProp.getTextSelectorProp(elem,animatorProps.s, container); 25 | this.s.t = animatorProps.s.t; 26 | } -------------------------------------------------------------------------------- /player/js/utils/text/TextSelectorProperty.js: -------------------------------------------------------------------------------- 1 | var TextSelectorProp = (function(){ 2 | var max = Math.max; 3 | var min = Math.min; 4 | var floor = Math.floor; 5 | 6 | function TextSelectorProp(elem,data){ 7 | this._currentTextLength = -1; 8 | this.k = false; 9 | this.data = data; 10 | this.elem = elem; 11 | this.comp = elem.comp; 12 | this.finalS = 0; 13 | this.finalE = 0; 14 | this.initDynamicPropertyContainer(elem); 15 | this.s = PropertyFactory.getProp(elem,data.s || {k:0},0,0,this); 16 | if('e' in data){ 17 | this.e = PropertyFactory.getProp(elem,data.e,0,0,this); 18 | }else{ 19 | this.e = {v:100}; 20 | } 21 | this.o = PropertyFactory.getProp(elem,data.o || {k:0},0,0,this); 22 | this.xe = PropertyFactory.getProp(elem,data.xe || {k:0},0,0,this); 23 | this.ne = PropertyFactory.getProp(elem,data.ne || {k:0},0,0,this); 24 | this.a = PropertyFactory.getProp(elem,data.a,0,0.01,this); 25 | if(!this.dynamicProperties.length){ 26 | this.getValue(); 27 | } 28 | } 29 | 30 | TextSelectorProp.prototype = { 31 | getMult: function(ind) { 32 | if(this._currentTextLength !== this.elem.textProperty.currentData.l.length) { 33 | this.getValue(); 34 | } 35 | //var easer = bez.getEasingCurve(this.ne.v/100,0,1-this.xe.v/100,1); 36 | var easer = BezierFactory.getBezierEasing(this.ne.v/100,0,1-this.xe.v/100,1).get; 37 | var mult = 0; 38 | var s = this.finalS; 39 | var e = this.finalE; 40 | var type = this.data.sh; 41 | if(type == 2){ 42 | if(e === s){ 43 | mult = ind >= e ? 1 : 0; 44 | }else{ 45 | mult = max(0,min(0.5/(e-s) + (ind-s)/(e-s),1)); 46 | } 47 | mult = easer(mult); 48 | }else if(type == 3){ 49 | if(e === s){ 50 | mult = ind >= e ? 0 : 1; 51 | }else{ 52 | mult = 1 - max(0,min(0.5/(e-s) + (ind-s)/(e-s),1)); 53 | } 54 | 55 | mult = easer(mult); 56 | }else if(type == 4){ 57 | if(e === s){ 58 | mult = 0; 59 | }else{ 60 | mult = max(0,min(0.5/(e-s) + (ind-s)/(e-s),1)); 61 | if(mult<0.5){ 62 | mult *= 2; 63 | }else{ 64 | mult = 1 - 2*(mult-0.5); 65 | } 66 | } 67 | mult = easer(mult); 68 | }else if(type == 5){ 69 | if(e === s){ 70 | mult = 0; 71 | }else{ 72 | var tot = e - s; 73 | /*ind += 0.5; 74 | mult = -4/(tot*tot)*(ind*ind)+(4/tot)*ind;*/ 75 | ind = min(max(0,ind+0.5-s),e-s); 76 | var x = -tot/2+ind; 77 | var a = tot/2; 78 | mult = Math.sqrt(1 - (x*x)/(a*a)); 79 | } 80 | mult = easer(mult); 81 | }else if(type == 6){ 82 | if(e === s){ 83 | mult = 0; 84 | }else{ 85 | ind = min(max(0,ind+0.5-s),e-s); 86 | mult = (1+(Math.cos((Math.PI+Math.PI*2*(ind)/(e-s)))))/2; 87 | /* 88 | ind = Math.min(Math.max(s,ind),e-1); 89 | mult = (1+(Math.cos((Math.PI+Math.PI*2*(ind-s)/(e-1-s)))))/2; 90 | mult = Math.max(mult,(1/(e-1-s))/(e-1-s));*/ 91 | } 92 | mult = easer(mult); 93 | }else { 94 | if(ind >= floor(s)){ 95 | if(ind-s < 0){ 96 | mult = 1 - (s - ind); 97 | }else{ 98 | mult = max(0,min(e-ind,1)); 99 | } 100 | } 101 | mult = easer(mult); 102 | } 103 | return mult*this.a.v; 104 | }, 105 | getValue: function(newCharsFlag) { 106 | this.iterateDynamicProperties(); 107 | this._mdf = newCharsFlag || this._mdf; 108 | this._currentTextLength = this.elem.textProperty.currentData.l.length || 0; 109 | if(newCharsFlag && this.data.r === 2) { 110 | this.e.v = this._currentTextLength; 111 | } 112 | var divisor = this.data.r === 2 ? 1 : 100 / this.data.totalChars; 113 | var o = this.o.v/divisor; 114 | var s = this.s.v/divisor + o; 115 | var e = (this.e.v/divisor) + o; 116 | if(s>e){ 117 | var _s = s; 118 | s = e; 119 | e = _s; 120 | } 121 | this.finalS = s; 122 | this.finalE = e; 123 | } 124 | } 125 | extendPrototype([DynamicPropertyContainer], TextSelectorProp); 126 | 127 | function getTextSelectorProp(elem, data,arr) { 128 | return new TextSelectorProp(elem, data, arr); 129 | } 130 | 131 | return { 132 | getTextSelectorProp: getTextSelectorProp 133 | }; 134 | }()); 135 | 136 | -------------------------------------------------------------------------------- /tasks/build.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs-extra"); 2 | const cheerio = require("cheerio"); 3 | const package = require("../package.json"); 4 | 5 | const rootFolder = "player/"; 6 | const bm_version = package.version; 7 | const buildReducedVersion = process.argv[2] === "reduced"; 8 | 9 | function loadIndex() { 10 | return new Promise((resolve, reject) => { 11 | function onLoad(err, result) { 12 | if (err) { 13 | reject(err); 14 | } else { 15 | resolve(result); 16 | } 17 | } 18 | fs.readFile(`${rootFolder}index.html`, "utf8", onLoad); 19 | }); 20 | } 21 | 22 | function parseHTML(html) { 23 | return new Promise((resolve, reject) => { 24 | try { 25 | const $ = cheerio.load(html); 26 | resolve($); 27 | } catch (err) { 28 | reject(err); 29 | } 30 | }); 31 | } 32 | 33 | function getScripts($) { 34 | return new Promise((resolve, reject) => { 35 | try { 36 | const defaultBuilds = ["canvas", "canvas_light"]; 37 | const scriptNodes = []; 38 | let shouldAddToScripts = false; 39 | $("head") 40 | .contents() 41 | .each((index, node) => { 42 | if (node.nodeType === 8 && node.data.indexOf("build:js") !== -1) { 43 | shouldAddToScripts = true; 44 | } else if (shouldAddToScripts) { 45 | if (node.type === "script") { 46 | scriptNodes.push(node); 47 | } else if ( 48 | node.nodeType === 8 && 49 | node.data.indexOf("endbuild") !== -1 50 | ) { 51 | shouldAddToScripts = false; 52 | } 53 | } 54 | }); 55 | 56 | const scripts = scriptNodes.map((node) => { 57 | const builds = node.attribs["data-builds"] 58 | ? node.attribs["data-builds"].split(",") 59 | : defaultBuilds; 60 | return { 61 | src: node.attribs.src, 62 | builds: builds, 63 | }; 64 | }); 65 | resolve(scripts); 66 | } catch (err) { 67 | reject(err); 68 | } 69 | }); 70 | } 71 | 72 | function concatScripts(scripts, build) { 73 | return new Promise((resolve, reject) => { 74 | // Concatenating scripts 75 | try { 76 | let scriptsString = ""; 77 | scripts.forEach((script) => { 78 | if (script.builds.indexOf(build) !== -1) { 79 | scriptsString += fs.readFileSync(`${rootFolder}${script.src}`, { 80 | encoding: "utf8", 81 | }); 82 | scriptsString += "\r\n"; 83 | } 84 | }); 85 | resolve(scriptsString); 86 | } catch (err) { 87 | reject(err); 88 | } 89 | }); 90 | } 91 | 92 | function wrapScriptWithModule(code) { 93 | return new Promise((resolve, reject) => { 94 | try { 95 | // Wrapping with module 96 | let wrappedCode = fs.readFileSync(`${rootFolder}js/module.js`, "utf8"); 97 | wrappedCode = wrappedCode.replace("/*<%= contents %>*/", code); 98 | wrappedCode = wrappedCode.replace("[[BM_VERSION]]", bm_version); 99 | resolve(wrappedCode); 100 | } catch (err) { 101 | reject(err); 102 | } 103 | }); 104 | } 105 | 106 | async function buildVersion(scripts, version) { 107 | const code = await concatScripts(scripts, version.build); 108 | const wrappedCode = await wrapScriptWithModule(code); 109 | const processedCode = await version.process(wrappedCode); 110 | const saved = await save(processedCode, version.fileName); 111 | return true; 112 | } 113 | 114 | function save(code, fileName) { 115 | return new Promise((resolve, reject) => { 116 | fs.writeFile(`build/${fileName}`, code, (err) => { 117 | if (err) { 118 | reject(err); 119 | } else { 120 | resolve("File Saved"); 121 | } 122 | }); 123 | }); 124 | } 125 | 126 | function noop(code) { 127 | return Promise.resolve(code); 128 | } 129 | 130 | function buildVersions(scripts) { 131 | console.log("begin build "); 132 | return new Promise((resolve, reject) => { 133 | let versions = [ 134 | { 135 | fileName: "lottie_canvas.js", 136 | build: "canvas", 137 | process: noop, 138 | }, 139 | ]; 140 | 141 | if (buildReducedVersion) { 142 | versions = versions.splice(0, 1); 143 | } 144 | 145 | const buildProcesses = versions.map((version) => { 146 | return buildVersion(scripts, version); 147 | }); 148 | Promise.all(buildProcesses) 149 | .then(() => { 150 | resolve("Build Process Ended"); 151 | }) 152 | .catch((err) => { 153 | reject(err); 154 | }); 155 | }); 156 | } 157 | 158 | function handleError(err) { 159 | console.log(err); 160 | } 161 | 162 | async function build() { 163 | try { 164 | fs.emptyDir('build'); 165 | const htmlData = await loadIndex(); 166 | const parsedData = await parseHTML(htmlData); 167 | const scripts = await getScripts(parsedData); 168 | const result = await buildVersions(scripts); 169 | console.log(result); 170 | } catch (err) { 171 | handleError(err); 172 | } 173 | } 174 | 175 | build(); 176 | -------------------------------------------------------------------------------- /tasks/watch.js: -------------------------------------------------------------------------------- 1 | const childProcess = require("child_process"); 2 | const watch = require("watch"); 3 | const path = require("path"); 4 | 5 | function runScript(scriptPath, processArguments, callback) { 6 | // keep track of whether callback has been invoked to prevent multiple invocations 7 | let invoked = false; 8 | 9 | const process = childProcess.fork(scriptPath, processArguments); 10 | 11 | // listen for errors as they may prevent the exit event from firing 12 | process.on("error", function (err) { 13 | if (invoked) return; 14 | invoked = true; 15 | callback(err); 16 | }); 17 | 18 | // execute the callback once the process has finished running 19 | process.on("exit", function (code) { 20 | if (invoked) return; 21 | invoked = true; 22 | const err = code === 0 ? null : new Error("exit code " + code); 23 | callback(err); 24 | }); 25 | } 26 | 27 | watch.watchTree(path.join(__dirname, "../player/js"), function (f, curr, prev) { 28 | runScript(path.join(__dirname, "./build.js"), ["reduced"], function (err) { 29 | if (err) throw err; 30 | console.log("--------------------------------"); 31 | console.log("rebuild lottie-nodejs library"); 32 | }); 33 | }); 34 | --------------------------------------------------------------------------------