Imaginemos que tenemos la necesidad de exportar en algún tipo de formato multimedia el contenido que tenemos en nuestro elemento <canvas>
. Existen formas de hacerlo, así que vamos a revisar varios ejemplos.
Exportar un canvas
Nuestro elemento <canvas>
tiene tres métodos interesantes para exportar su contenido:
Método | Descripción |
---|---|
.toDataURL(type, quality) | Convierte el lienzo en una imagen formato type representada como |
.toBlob(fn, type, quality) | Convierte el lienzo en un BLOB (Binary Large Object) para manipulación eficiente. |
.captureStream() | Permite capturar el contenido del lienzo como un stream de datos, convertible a video. |
Vamos a ver varios ejemplos donde utilizaremos cada uno de ellos.
Mediante el método .toDataURL()
podemos convertir la imagen que se ve en el lienzo en una imagen de tipo Data URI, es decir, una cadena de texto (generalmente, muy grande) que contiene la información de la imagen, y que se puede mostrar al colocarla como URL.
En este ejemplo, guardamos dicho dataURL
lo añadimos al atributo src
de una <img>
HTML. Con ello, es suficiente para mostrar la imagen:
<canvas></canvas>
<script>
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
canvas.style.background = "#ccc";
ctx.fillStyle = "blue";
ctx.fillRect(50, 50, 100, 100);
// Convierte el lienzo a Data URI en formato PNG
const dataURL = canvas.toDataURL("image/png", 1.0);
const img = document.createElement("img");
img.src = dataURL;
document.body.append(img);
</script>
Observa que en este caso, el fondo gris no ha sido «copiado». Esto ocurre así porque ese color se está añadiendo mediante CSS y no forma parte del canvas.
Una forma alternativa de guardar la imagen del canvas, es utilizando el método .toBlob()
. Este método convierte la información del canvas en un BLOB (Binary Large Object), que es un formato que permite almacenar grandes cantidades inmutables de datos binarios.
Una de las características importantes de estos BLOB es que son ideales para trabajar con grandes cantidades de datos, ya que se manipulan como referencias a memoria, en lugar de como cadenas de texto.
Veamos un ejemplo de uso de este método:
<canvas></canvas>
<script>
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
canvas.style.background = "#ccc";
ctx.fillStyle = "blue";
ctx.fillRect(50, 50, 100, 100);
// Convierte el lienzo en un BLOB y permite descargarlo mediante un enlace
canvas.toBlob((blob) => {
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
console.log({ blob, url: a.href })
a.download = "canvas-image.png";
a.textContent = "Descargar";
document.body.append(a);
}, "image/png", 1.0);
</script>
Observa que la función que se le pasa por parámetro es la encargada de realizar toda la lógica. En el segundo parámetro se le pasa el formato de la imagen y en el tercero, la calidad de la imagen, siendo un valor 0
a 1
.
Por último, también podemos crear un video a partir de una animación de un elemento canvas. Para ello, vamos a utilizar el método .captureStream()
, que permite ir capturando los fotogramas del canvas, para crear un video. Vamos a explicar los detalles clave que hemos hecho:
- 1️⃣ En el canvas, se muestra un cuadrado que va cambiando de color de forma aleatoria.
- 2️⃣ Si pulsamos en el botón
Record
comenzamos a capturar los datos del canvas y guardándolos. - 3️⃣ En
recordedChunks
vamos guardando los datos capturados en cuanto hay disponibles. - 4️⃣ Con el
MediaRecorder
establecemos un mecanismo para grabar en video. - 5️⃣ Si pulsamos en el botón
Stop record
, paramos la grabación y activamos un enlace de descarga. - 6️⃣ Al pulsar en ese enlace, el se descarga el video en formato MP4.
Echemos un vistazo a dicho código:
<canvas></canvas>
<button class="record">Record</button>
<a class="download"></a>
<script>
const recordButton = document.querySelector(".record");
const downloadLink = document.querySelector(".download");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
canvas.style.background = "#ccc";
ctx.fillStyle = "red";
ctx.fillRect(50, 50, 100, 100);
// Dibuja un cuadrado de un color aleatorio cada 0.5seg
setInterval(() => {
const r = Math.random() * 255;
const g = Math.random() * 255;
const b = Math.random() * 255;
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
ctx.fillRect(50, 50, 100, 100);
}, 500);
let mediaRecorder;
let recordedChunks = [];
recordButton.addEventListener("click", () => {
const stream = canvas.captureStream();
const video = document.createElement("video");
video.muted = true;
video.autoplay = true;
video.srcObject = stream;
if (!mediaRecorder || mediaRecorder.state === "inactive") {
recordedChunks = [];
mediaRecorder = new MediaRecorder(stream, { mimeType: "video/mp4" });
mediaRecorder.addEventListener("dataavailable", (event) => {
if (event.data.size > 0) {
recordedChunks.push(event.data);
}
});
mediaRecorder.addEventListener("stop", () => {
const blob = new Blob(recordedChunks, { type: "video/mp4" });
const url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.textContent = "Download";
downloadLink.download = "canvas-animation.mp4";
});
mediaRecorder.start();
recordButton.textContent = "Stop Recording";
} else {
mediaRecorder.stop();
recordButton.textContent = "Start Recording";
}
});
</script>
Con estos mecanismos, podemos utilizar un elemento HTML <canvas>
para generar información multimedia, tanto en imagen como en video, permitiéndo descargarlo y guardarlo en nuestro sistema.