Home | History | Annotate | Download | only in lottiecap
      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4     <title>Lottie Filmstrip Capture</title>
      5     <meta charset="utf-8" />
      6     <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
      7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
      8     <script src="/lottie.js" type="text/javascript" charset="utf-8"></script>
      9     <style type="text/css" media="screen">
     10       body,
     11       main,
     12       .anim {
     13         margin: 0;
     14         padding: 0;
     15       }
     16 
     17       main {
     18         display: flex;
     19         width: 1000px;
     20         height: 1000px;
     21         flex-flow: row wrap;
     22       }
     23     </style>
     24 </head>
     25 <body>
     26   <main>
     27     <div class=anim></div>
     28   </main>
     29   <script type="text/javascript" charset="utf-8">
     30     (function () {
     31       const TILE_COUNT = 5; // Number of tiles in x or y direction.
     32       const TARGET_SIZE = 1000; // Image size in pixels both x and y direction.
     33       const PATH = '/lottie.json';
     34 
     35       let renderer = 'svg';
     36       let hash = window.location.hash;
     37       if (hash) {
     38         renderer = hash.slice(1);
     39       }
     40 
     41       // This global is used by puppeteer to determine if all tiles have finished drawing.
     42       window._tileCount = 0;
     43 
     44       // First load the animation for just a single tile
     45       // so we can read out some values and calculate what
     46       // the filmstrip should look like.
     47       let anim = lottie.loadAnimation({
     48         container: document.querySelector('.anim'),
     49         renderer: renderer,
     50         loop: false,
     51         autoplay: true,
     52         path: PATH,
     53         rendererSettings: {
     54           preserveAspectRatio:'xMidYMid meet'
     55         },
     56       });
     57 
     58       anim.addEventListener('data_ready', (e) => {
     59         // Once the first tile is loaded, calculate what
     60         // the filmstrip should look like.
     61         let animationData = anim.animationData;
     62         let totalFrames = anim.totalFrames;
     63         // t_rate mimics DMSrcSink.cpp::SkottieSrc::draw
     64         let t_rate = 1.0 / (TILE_COUNT * TILE_COUNT - 1);
     65 
     66         let main = document.querySelector('main');
     67 
     68         // Clear out the first div now that our measurements are done.
     69         main.firstElementChild.remove();
     70 
     71         // Add in all the tiles.
     72         for (let i = 0; i < TILE_COUNT*TILE_COUNT; i++) {
     73           let div = document.createElement('div');
     74           div.classList.add('anim');
     75           div.style.width = (TARGET_SIZE / TILE_COUNT) + 'px';
     76           div.style.height = (TARGET_SIZE / TILE_COUNT) + 'px';
     77           main.appendChild(div);
     78 
     79           // create a new animation for each tile. It is tempting to try having
     80           // one animation and "clone" each frame, but that doesn't work
     81           // because of how bodymovin cleans up the URLObjects that are the path
     82           // data for the svgs.
     83           // We can re-use the animationData to avoid having to hit the
     84           // (local) network a bunch of times.
     85           let anim = lottie.loadAnimation({
     86             container: div,
     87             renderer: renderer,
     88             loop: false,
     89             autoplay: false,
     90             animationData: animationData,
     91             rendererSettings: {
     92               preserveAspectRatio:'xMidYMid meet'
     93             },
     94           });
     95 
     96           let t = Math.max(Math.min(t_rate * i, 1.0), 0.0);
     97           let seekToFrame = totalFrames * t;
     98           if (seekToFrame >= totalFrames) {
     99             // bodymovin player sometimes draws blank when requesting
    100             // to draw the very last frame.  Subtracting a small value
    101             // seems to fix this and make it draw the last frame.
    102             seekToFrame -= .001;
    103           }
    104 
    105           // don't need to wait for data_ready because it's instantly ready.
    106           console.log(`t = ${t}, go to frame ${seekToFrame}`);
    107           anim.goToAndStop(seekToFrame, true);
    108           window._tileCount += 1;
    109         }
    110       });
    111     })();
    112   
    113 
    114 
    115