1describe('CanvasKit\'s Animation', function() { 2 3 const LOTTIE_ANIMATIONS = ['lego_loader', 'drinks', 'confetti', 'onboarding']; 4 5 let container = document.createElement('div'); 6 document.body.appendChild(container); 7 8 9 beforeEach(function() { 10 container.innerHTML = ` 11 <canvas width=600 height=600 id=test></canvas>`; 12 }); 13 14 afterEach(function() { 15 container.innerHTML = ''; 16 }); 17 18 function fetchAndText(url) { 19 return new Promise(function(resolve, reject) { 20 fetch(url).then((resp) => { 21 resp.text().then((str) => { 22 expect(str).toBeTruthy(); 23 resolve(str); 24 }); 25 }).catch(reject); 26 }); 27 } 28 29 LOTTIE_ANIMATIONS.forEach((animStr) => { 30 let promises = [fetchAndText(`/assets/${animStr}.json`), LoadCanvasKit]; 31 32 it(`animation loading for ${animStr}`, function(done) { 33 let jsonStr = ''; 34 function setup(ctx) { 35 expect(jsonStr).toBeTruthy(); 36 } 37 38 function test(ctx) { 39 const animation = CanvasKit.MakeAnimation(jsonStr); 40 animation.delete(); 41 } 42 43 function teardown(ctx) {} 44 45 Promise.all(promises).then((responses) => { 46 // The result from the first promise, that is, the JSON string 47 // fetched by fetchAndText 48 jsonStr = responses[0]; 49 benchmarkAndReport(`${animStr}_animation_load`, setup, test, teardown).then(() => { 50 done(); 51 }).catch(reportError(done)); 52 }); 53 }); 54 55 it(`animation frames in order for ${animStr}`, function(done) { 56 let jsonStr = ''; 57 function setup(ctx) { 58 expect(jsonStr).toBeTruthy(); 59 ctx.animation = CanvasKit.MakeAnimation(jsonStr); 60 expect(ctx.animation).toBeTruthy(); 61 ctx.timer = 0; 62 } 63 64 function test(ctx) { 65 ctx.animation.seek(ctx.timer); 66 ctx.timer += 0.01; 67 if (ctx.timer > 1.0) { 68 ctx.timer = 0; 69 } 70 } 71 72 function teardown(ctx) { 73 ctx.animation.delete(); 74 } 75 76 Promise.all(promises).then((responses) => { 77 // The result from the first promise, that is, the JSON string 78 // fetched by fetchAndText 79 jsonStr = responses[0]; 80 benchmarkAndReport(`${animStr}_animation_in_order`, setup, test, teardown).then(() => { 81 done(); 82 }).catch(reportError(done)); 83 }); 84 }); 85 86 it(`animation frames in random order for ${animStr}`, function(done) { 87 let jsonStr = ''; 88 function setup(ctx) { 89 expect(jsonStr).toBeTruthy(); 90 ctx.animation = CanvasKit.MakeAnimation(jsonStr); 91 expect(ctx.animation).toBeTruthy(); 92 } 93 94 function test(ctx) { 95 ctx.animation.seek(Math.random()); 96 } 97 98 function teardown(ctx) { 99 ctx.animation.delete(); 100 } 101 102 Promise.all(promises).then((responses) => { 103 // The result from the first promise, that is, the JSON string 104 // fetched by fetchAndText 105 jsonStr = responses[0]; 106 benchmarkAndReport(`${animStr}_animation_random_order`, setup, test, teardown).then(() => { 107 done(); 108 }).catch(reportError(done)); 109 }); 110 }); 111 112 it(`renders to an HTML canvas ${animStr}`, function(done) { 113 let jsonStr = ''; 114 function setup(ctx) { 115 expect(jsonStr).toBeTruthy(); 116 ctx.animation = CanvasKit.MakeAnimation(jsonStr); 117 expect(ctx.animation).toBeTruthy(); 118 ctx.animation.seek(0.5); 119 ctx.surface = CanvasKit.MakeCanvasSurface('test'); 120 ctx.canvas = ctx.surface.getCanvas(); 121 ctx.clear = CanvasKit.Color(255, 255, 255, 0.0); // transparent 122 } 123 124 function test(ctx) { 125 // This emulates what would need to be done do accurately 126 // draw one frame. 127 ctx.canvas.clear(ctx.clear); 128 ctx.animation.render(ctx.canvas); 129 ctx.surface.flush(); 130 } 131 132 function teardown(ctx) { 133 ctx.animation.delete(); 134 ctx.surface.dispose(); // ctx.canvas will also be cleaned up 135 } 136 137 Promise.all(promises).then((responses) => { 138 // The result from the first promise, that is, the JSON string 139 // fetched by fetchAndText 140 jsonStr = responses[0]; 141 benchmarkAndReport(`${animStr}_animation_render_flush`, setup, test, teardown).then(() => { 142 done(); 143 }).catch(reportError(done)); 144 }); 145 }); 146 147 }); 148 149}); 150