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