115 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			HTML
		
	
	
	
<!DOCTYPE html>
 | 
						|
<html>
 | 
						|
<head>
 | 
						|
  <title>Lottie Filmstrip Capture</title>
 | 
						|
  <meta charset="utf-8" />
 | 
						|
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
						|
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
						|
  <script src="/lottie.js" type="text/javascript" charset="utf-8"></script>
 | 
						|
  <style type="text/css" media="screen">
 | 
						|
    body,
 | 
						|
    main,
 | 
						|
    .anim {
 | 
						|
      margin: 0;
 | 
						|
      padding: 0;
 | 
						|
    }
 | 
						|
 | 
						|
    main {
 | 
						|
      display: flex;
 | 
						|
      width: 1000px;
 | 
						|
      height: 1000px;
 | 
						|
      flex-flow: row wrap;
 | 
						|
    }
 | 
						|
  </style>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
  <main>
 | 
						|
    <div class=anim></div>
 | 
						|
  </main>
 | 
						|
  <script type="text/javascript" charset="utf-8">
 | 
						|
    (function () {
 | 
						|
      const TILE_COUNT = 5; // Number of tiles in x or y direction.
 | 
						|
      const TARGET_SIZE = 1000; // Image size in pixels both x and y direction.
 | 
						|
      const PATH = '/lottie.json';
 | 
						|
 | 
						|
      let renderer = 'svg';
 | 
						|
      let hash = window.location.hash;
 | 
						|
      if (hash) {
 | 
						|
        renderer = hash.slice(1);
 | 
						|
      }
 | 
						|
 | 
						|
      // This global is used by puppeteer to determine if all tiles have finished drawing.
 | 
						|
      window._tileCount = 0;
 | 
						|
 | 
						|
      // First load the animation for just a single tile
 | 
						|
      // so we can read out some values and calculate what
 | 
						|
      // the filmstrip should look like.
 | 
						|
      let anim = lottie.loadAnimation({
 | 
						|
        container: document.querySelector('.anim'),
 | 
						|
        renderer: renderer,
 | 
						|
        loop: false,
 | 
						|
        autoplay: true,
 | 
						|
        path: PATH,
 | 
						|
        rendererSettings: {
 | 
						|
          preserveAspectRatio:'xMidYMid meet'
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      anim.addEventListener('data_ready', (e) => {
 | 
						|
        // Once the first tile is loaded, calculate what
 | 
						|
        // the filmstrip should look like.
 | 
						|
        let animationData = anim.animationData;
 | 
						|
        let totalFrames = anim.totalFrames;
 | 
						|
        // t_rate mimics DMSrcSink.cpp::SkottieSrc::draw
 | 
						|
        let t_rate = 1.0 / (TILE_COUNT * TILE_COUNT - 1);
 | 
						|
 | 
						|
        let main = document.querySelector('main');
 | 
						|
 | 
						|
        // Clear out the first div now that our measurements are done.
 | 
						|
        main.firstElementChild.remove();
 | 
						|
 | 
						|
        // Add in all the tiles.
 | 
						|
        for (let i = 0; i < TILE_COUNT*TILE_COUNT; i++) {
 | 
						|
          let div = document.createElement('div');
 | 
						|
          div.classList.add('anim');
 | 
						|
          div.style.width = (TARGET_SIZE / TILE_COUNT) + 'px';
 | 
						|
          div.style.height = (TARGET_SIZE / TILE_COUNT) + 'px';
 | 
						|
          main.appendChild(div);
 | 
						|
 | 
						|
          // create a new animation for each tile. It is tempting to try having
 | 
						|
          // one animation and "clone" each frame, but that doesn't work
 | 
						|
          // because of how bodymovin cleans up the URLObjects that are the path
 | 
						|
          // data for the svgs.
 | 
						|
          // We can re-use the animationData to avoid having to hit the
 | 
						|
          // (local) network a bunch of times.
 | 
						|
          let anim = lottie.loadAnimation({
 | 
						|
            container: div,
 | 
						|
            renderer: renderer,
 | 
						|
            loop: false,
 | 
						|
            autoplay: false,
 | 
						|
            animationData: animationData,
 | 
						|
            rendererSettings: {
 | 
						|
              preserveAspectRatio:'xMidYMid meet'
 | 
						|
            },
 | 
						|
          });
 | 
						|
 | 
						|
          let t = Math.max(Math.min(t_rate * i, 1.0), 0.0);
 | 
						|
          let seekToFrame = totalFrames * t;
 | 
						|
          if (seekToFrame >= totalFrames) {
 | 
						|
            // bodymovin player sometimes draws blank when requesting
 | 
						|
            // to draw the very last frame.  Subtracting a small value
 | 
						|
            // seems to fix this and make it draw the last frame.
 | 
						|
            seekToFrame -= .001;
 | 
						|
          }
 | 
						|
 | 
						|
          // don't need to wait for data_ready because it's instantly ready.
 | 
						|
          console.log(`t = ${t}, go to frame ${seekToFrame}`);
 | 
						|
          anim.goToAndStop(seekToFrame, true);
 | 
						|
          window._tileCount += 1;
 | 
						|
        }
 | 
						|
      });
 | 
						|
    })();
 | 
						|
  </script>
 | 
						|
</body>
 | 
						|
</html>
 |