Published
Edited
Jan 30, 2022
Importers
2 stars
Insert cell
Insert cell
Insert cell
generatorExample = example
Insert cell
canvasRecord(generatorExample, { generator: true })
Insert cell
Insert cell
Insert cell
canvasRecord(interactiveExample)
Insert cell
Insert cell
Insert cell
canvasRecord(webglExample)
Insert cell
Insert cell
//
// Adapted from https://observablehq.com/@mourner/canvas-recorder
//
function canvasRecord(canvas, options = {}) {
if (canvas.__recordInterface) {
// maintain state for canvases updated with the generator pattern
return canvas.__recordInterface;
}
console.log("redefined");
let {
type = "webm",
maxchunks = 600,
timeslice = 100,
fps = 30,
generator = false
} = options;
let chunks = [];
let MediaRecorder = window.MediaRecorder;
if (!MediaRecorder || !MediaRecorder.isTypeSupported(`video/${type}`)) {
return html`<span style="color:red">Your browser doesn't support MediaRecorder/${type}.</span>`;
}

const downloadButton = htl.html`<button>download`;
const startPauseButton = htl.html`<button>record`;
const stopButton = htl.html`<button>stop`;
const message = htl.html`<span>${status}`;
const recordInterface = htl.html`${startPauseButton}${stopButton}${downloadButton}<br>${message}`;

let recorder = new MediaRecorder(canvas.captureStream(fps), {
mimeType: `video/${type}`
});
recordInterface._recorder = recorder;

const setButtonState = () => {
downloadButton.disabled = chunks.length == 0;
stopButton.disabled = recorder.state == "inactive";
};

setButtonState();

const stopRecording = () => {
if (recorder.state == "paused" || recorder.state == "recording") {
console.log("Stopping");
recorder.stop();
}
startPauseButton.innerHTML = "record";
message.innerHTML = `${recorder.state} chunks:${chunks.length}`;
setButtonState();
};

stopButton.onclick = stopRecording;

downloadButton.onclick = () => {
if (chunks.length == 0) {
message.innerHTML = `No recording to save`;
setButtonState();
return;
}
stopRecording();
var blob = new Blob(chunks, { type: `video/${type}` });
var link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = `canvas.${type}`;
link.click();
message.innerHTML = "file saved";
setButtonState();
};

startPauseButton.onclick = () => {
if (recorder.state == "inactive") {
chunks = [];
recorder.ondataavailable = (e) => {
chunks.push(e.data);
message.innerHTML = "recorded chunk " + chunks.length;
if (chunks.length > maxchunks) stopRecording();
};
recorder.start(timeslice);
startPauseButton.innerHTML = "pause";
} else if (recorder.state == "paused") {
recorder.resume();
startPauseButton.innerHTML = "pause";
} else if (recorder.state == "recording") {
recorder.pause();
startPauseButton.innerHTML = "resume";
}
message.innerHTML = `${recorder.state} chunks:${chunks.length}`;
setButtonState();
};
if (generator) canvas.__recordInterface = recordInterface;
return recordInterface;
}
Insert cell
Insert cell
Insert cell
Insert cell
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