1<!DOCTYPE html> 2<html> 3<head> 4 <title>Skottie-WASM Perf</title> 5 <meta charset="utf-8" /> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <script src="res/canvaskit.js" type="text/javascript" charset="utf-8"></script> 9 <style type="text/css" media="screen"> 10 body { 11 margin: 0; 12 padding: 0; 13 } 14 </style> 15</head> 16<body> 17 <main> 18 <canvas id=anim width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas> 19 </main> 20 <script type="text/javascript" charset="utf-8"> 21 const WIDTH = 1000; 22 const HEIGHT = 1000; 23 const LOTTIE_JSON_PATH = '/res/lottie.json'; 24 const MAX_FRAMES = 25; 25 const MAX_LOOPS = 25; 26 const MAX_SAMPLE_MS = 60*1000; // in case something takes a while, stop after 60 seconds. 27 (function() { 28 const loadKit = CanvasKitInit({ 29 locateFile: (file) => '/res/' + file, 30 }); 31 32 const loadLottie = fetch(LOTTIE_JSON_PATH).then((resp) => { 33 return resp.text(); 34 }); 35 36 Promise.all([loadKit, loadLottie]).then((values) => { 37 const [CanvasKit, json] = values; 38 39 const animation = CanvasKit.MakeManagedAnimation(json, null); 40 if (!animation) { 41 window._error = 'Could not process JSON'; 42 return 43 } 44 45 let surface = null; 46 if (window.location.hash.indexOf('gpu') !== -1) { 47 surface = CanvasKit.MakeWebGLCanvasSurface('anim'); 48 if (!surface) { 49 window._error = 'Could not make GPU surface'; 50 return; 51 } 52 let c = document.getElementById('anim'); 53 // If CanvasKit was unable to instantiate a WebGL context, it will fallback 54 // to CPU and add a ck-replaced class to the canvas element. 55 if (c.classList.contains('ck-replaced')) { 56 window._error = 'fell back to CPU'; 57 return; 58 } 59 } else { 60 surface = CanvasKit.MakeSWCanvasSurface('anim'); 61 if (!surface) { 62 window._error = 'Could not make CPU surface'; 63 return; 64 } 65 } 66 const canvas = surface.getCanvas(); 67 68 const t_rate = 1.0 / (MAX_FRAMES-1); 69 let seek = 0; 70 let frame = 0; 71 let loop = 0; 72 const damageRect = Float32Array.of(0, 0, 0, 0); 73 const bounds = CanvasKit.LTRBRect(0, 0, WIDTH, HEIGHT); 74 const start = performance.now(); 75 76 const drawFrame = () => { 77 if ((performance.now() - start) > MAX_SAMPLE_MS) { 78 // This global variable signals we are done. 79 window._skottieDone = true; 80 return; 81 } 82 if (frame >= MAX_FRAMES) { 83 // Reached the end of one loop. 84 loop++; 85 if (loop == MAX_LOOPS) { 86 // This global variable signals we are done. 87 window._skottieDone = true; 88 return; 89 } 90 // Reset frame and seek to restart the loop. 91 frame = 0; 92 seek = 0; 93 } 94 95 let damage = animation.seek(seek, damageRect); 96 if (damage[2] > damage[0] && damage[3] > damage[1]) { 97 animation.render(canvas, bounds); 98 surface.flush(); 99 } 100 console.log(`Used seek: ${seek}`); 101 seek += t_rate; 102 frame++; 103 window.requestAnimationFrame(drawFrame); 104 }; 105 window.requestAnimationFrame(drawFrame); 106 }); 107 })(); 108 </script> 109</body> 110</html> 111