Published
Edited
Dec 2, 2020
Importers
4 stars
Insert cell
Insert cell
Insert cell
DOM.download(async () => {
const ctx = DOM.context2d(160, 90);
const recorder = new CanvasRecorder(ctx.canvas);
const frames = 100;
for(let frame = 0; frame < frames; frame += 1) {
renderFrame(ctx, frame);
await recorder.captureFrame();
}

return recorder.stop();
}, 'canvas.webm', 'Render video');
Insert cell
example = {
const ctx = DOM.context2d(160, 90);
let frame = 0;
while (true) {
renderFrame(ctx, frame);
frame += 1;
yield ctx.canvas;
}
}
Insert cell
function renderFrame(ctx, count) {
ctx.font = '48px sans-serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'limegreen';
ctx.fillRect(0, 0, 160, 90);
ctx.fillStyle = 'white';
ctx.fillText(count, 80, 60);
}
Insert cell
Insert cell
class CanvasRecorder {
constructor(canvas) {
const mediaStream = canvas.captureStream(0);
this.chunks = [];
this.mimeType = 'video/webm';
this.recorder = new MediaRecorder(mediaStream, {mimeType: this.mimeType});
this.recorder.start();
this.videoTrack = mediaStream.getVideoTracks()[0];
}
captureFrame() {
return new Promise((resolve) => {
this.videoTrack.requestFrame();
this.recorder.ondataavailable = ({ data }) => {
if (data.size === 0) {
this.recorder.requestData();
} else {
this.chunks.push(data);
this.recorder.ondataavailable = null;
resolve();
}
};
this.recorder.requestData();
});
}
stop() {
this.recorder.stop();
return new Blob(this.chunks, {type: this.mimeType});
}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more