Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 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 | |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 35 | let renderer = 'svg'; |
| 36 | let hash = window.location.hash; |
| 37 | if (hash) { |
| 38 | renderer = hash.slice(1); |
| 39 | } |
| 40 | |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 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'), |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 49 | renderer: renderer, |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 50 | loop: false, |
| 51 | autoplay: true, |
| 52 | path: PATH, |
| 53 | rendererSettings: { |
| 54 | preserveAspectRatio:'xMidYMid meet' |
| 55 | }, |
| 56 | }); |
| 57 | |
Joe Gregorio | 7e86547 | 2018-03-20 16:03:13 -0400 | [diff] [blame] | 58 | anim.addEventListener('data_ready', (e) => { |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 59 | // Once the first tile is loaded, calculate what |
| 60 | // the filmstrip should look like. |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 61 | let animationData = anim.animationData; |
Kevin Lubick | 085e8ea | 2018-08-29 13:52:10 -0400 | [diff] [blame] | 62 | let totalFrames = anim.totalFrames; |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 63 | // t_rate mimics DMSrcSink.cpp::SkottieSrc::draw |
| 64 | let t_rate = 1.0 / (TILE_COUNT * TILE_COUNT - 1); |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 65 | |
| 66 | let main = document.querySelector('main'); |
| 67 | |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 68 | // Clear out the first div now that our measurements are done. |
| 69 | main.firstElementChild.remove(); |
| 70 | |
Joe Gregorio | 7e86547 | 2018-03-20 16:03:13 -0400 | [diff] [blame] | 71 | // Add in all the tiles. |
| 72 | for (let i = 0; i < TILE_COUNT*TILE_COUNT; i++) { |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 73 | let div = document.createElement('div'); |
| 74 | div.classList.add('anim'); |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 75 | div.style.width = (TARGET_SIZE / TILE_COUNT) + 'px'; |
| 76 | div.style.height = (TARGET_SIZE / TILE_COUNT) + 'px'; |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 77 | main.appendChild(div); |
| 78 | |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 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. |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 85 | let anim = lottie.loadAnimation({ |
| 86 | container: div, |
| 87 | renderer: renderer, |
| 88 | loop: false, |
Joe Gregorio | 7e86547 | 2018-03-20 16:03:13 -0400 | [diff] [blame] | 89 | autoplay: false, |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 90 | animationData: animationData, |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 91 | rendererSettings: { |
| 92 | preserveAspectRatio:'xMidYMid meet' |
| 93 | }, |
| 94 | }); |
Joe Gregorio | 7e86547 | 2018-03-20 16:03:13 -0400 | [diff] [blame] | 95 | |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 96 | let t = Math.max(Math.min(t_rate * i, 1.0), 0.0); |
Kevin Lubick | 085e8ea | 2018-08-29 13:52:10 -0400 | [diff] [blame] | 97 | let seekToFrame = totalFrames * t; |
| 98 | if (seekToFrame >= totalFrames) { |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 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. |
Kevin Lubick | 085e8ea | 2018-08-29 13:52:10 -0400 | [diff] [blame] | 102 | seekToFrame -= .001; |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 103 | } |
| 104 | |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 105 | // don't need to wait for data_ready because it's instantly ready. |
Kevin Lubick | c5fe15d | 2018-08-29 09:52:52 -0400 | [diff] [blame] | 106 | console.log(`t = ${t}, go to frame ${seekToFrame}`); |
| 107 | anim.goToAndStop(seekToFrame, true); |
Kevin Lubick | 82999c0 | 2018-08-28 10:52:18 -0400 | [diff] [blame] | 108 | window._tileCount += 1; |
Joe Gregorio | 0060c33 | 2018-03-19 14:26:58 -0400 | [diff] [blame] | 109 | } |
| 110 | }); |
| 111 | })(); |
| 112 | </script> |
| 113 | </body> |
| 114 | </html> |