Cómo renderizar una cadena/archivo SVG en un canvas y exportarlo a PNG o JPEG con una resolución personalizada (preservando la calidad) en JavaScript

Cómo renderizar una cadena/archivo SVG en un canvas y exportarlo a PNG o JPEG con una resolución personalizada (preservando la calidad) en JavaScript

La manipulación de imágenes siempre ha sido un poco complicada, especialmente cuando quieres hacerlo con un lenguaje como JavaScript y como si no fuera suficiente, directamente en el navegador. En los últimos días, he estado trabajando con una biblioteca muy especial llamada dom-to-image , esta biblioteca te permite convertir cualquier nodo DOM arbitrario en una imagen vectorial (SVG) o raster (PNG o JPEG) con JavaScript puro . He usado esta biblioteca para simplemente capturar un elemento DOM en el navegador para permitir que el usuario descargue la imagen y eso es todo.

En teoría, es bastante simple ya que el DOM es solo una colección de botones con emojis en el centro y se ve así:

Buttons PNG

Ten en cuenta que la imagen anterior es una captura de pantalla realizada con una herramienta externa y mantiene el tamaño original. Ahora, si decido exportar los elementos DOM usando la biblioteca mencionada en JPEG o PNG, perderá calidad drásticamente:

Buttons Small Exported Image

No es culpa de la biblioteca, por supuesto, ya que está rasterizando los elementos DOM como una imagen en formato PNG, sin embargo, se ve tan mal porque los botones son realmente pequeños en mi pantalla. Entonces, la solución sería agrandar los botones o trabajar con SVG en lugar de la versión rasterizada de los elementos DOM. Como sabrás, se puede aumentar y reducir la escala de SVG a cualquier tamaño que desees sin perder calidad en absoluto. Si los elementos DOM se exportan a SVG, puedes cambiar su tamaño al tamaño que desee, por ejemplo, el siguiente código representará el elemento DOM seleccionado a SVG y lo mostrará en una nueva pestaña del navegador:

let domNode = document.getElementById("myDiv");

// 1. Renderizar el nodo seleccionado a SVG
domtoimage.toSvg(domNode).then(function(SVG){
    
    // 2. Cargue la cadena SVG (se parece a esto:
    // data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="1623" height="64"><foreignObject x="0" y="0" width="100%" height="100%"><div id="myDiv" ....
    let image = new Image();
    image.src = SVG;

    // 3. Inicie una nueva pestaña en el navegador y cargue la imagen para ver la vista previa
    let newWindow = window.open("");
    newWindow.document.write(image.outerHTML);
});

Luego, en la nueva pestaña, verás que la imagen se ve bastante nítida y puede cambiar el tamaño de la imagen al tamaño que desees sin perder calidad (lo cambiamos a una imagen de 3500px, que es bastante grande en comparación con el tamaño original del botones):

Upscaled SVG Dom To Image

Por lo tanto, puedes rasterizarlo más tarde en un formato popular como PNG o JPEG, ¡pero con una calidad decente! En este tutorial, te mostraré cómo usar JavaScript fácilmente para representar una cadena SVG o un archivo SVG en una imagen y cambiar su tamaño al tamaño que desees manteniendo su calidad original.

1. Crea/obten la Data URL del SVG

Las URL de datos, las URL con el prefijo del data:esquema, permiten a los creadores de contenido incrustar archivos pequeños en línea en los documentos. En nuestro caso, nuestro esquema de datos para archivos SVG será:

Importante: es mejor si codifica en URL los datos SVG simples para codificar caracteres que no deberían aparecer en las URL.

data:image/svg+xml;charset=utf-8,[Los datos sin formato codificados en URL de SVG deben estar aquí]

Ten en cuenta que, a diferencia de otros formatos codificados con Base64, necesitaremos los datos sin formato en la URL de datos. Para este ejemplo, usaremos el conocido SVG Tiger de Wikipedia . La cadena SVG puede provenir de cualquier lugar, puede descargarse de un recurso web, crearse dentro del navegador o ser la salida de la biblioteca dom-to-image, el objetivo de este paso es que sepas que debe estar en Formato de URL de datos.

2. Prueba si el SVG se puede renderizar en una imagen

Para probar si su URL de datos SVG creada es válida, puede usarla fácilmente como fuente de un elemento de imagen en HTML. En este ejemplo, usaremos el mencionado SVG Tiger de Wikipedia y lo crearemos manualmente, almacenando el SVG en una variable de cadena, luego anteponiendo el esquema de URL de datos al SVG codificado en URL:

<!-- Un elemento de imagen donde se mostrará DataURL -->
<img src="" id="test" />
<script>
    // 1. Preparar cadena SVG
    let SVGString = `
        <svg id="svg2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 900" version="1.1">
            <g id="g4" fill="none" transform="matrix(1.7656463,0,0,1.7656463,324.90716,255.00942)">
                <g id="g6" stroke-width="0.17200001" stroke="#000" fill="#FFF">
                <path id="path8" d="m-122.3,84.285s0.1,1.894-0.73,1.875c-0.82-0.019-17.27-48.094-37.8-45.851,0,0,17.78-7.353,38.53,43.976z"/>
            </g>

            ....

            .... (resto de la cadena SVG, tenga en cuenta que eliminamos la siguiente cadena del SVG: <?xml version="1.0" encoding="UTF-8" standalone="no"?>)

            ....
        </svg>
    `;

    // 2. Convertir a URL de datos
    let dataURL = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(SVGString);

    // 3. Establecer DataURL como fuente de la imagen de prueba
    document.getElementById("test").src = dataURL;
</script>

Puedes ver esto en acción en el siguiente Fiddle que debería mostrar el tigre SVG en el elemento Imagen:

Sabiendo ahora que la URL de datos SVG es válida (siempre que la imagen que esperaba del SVG dado aparezca en el elemento img), puedes continuar con el siguiente paso.

3. Renderiza SVG en Canvas y expórtelo como una imagen de cualquier tamaño

Ahora es el momento de implementar lo que está buscando, convirtiendo el SVG en un lienzo para cambiar su tamaño a cualquier tamaño que desee. La lógica a conseguir es la siguiente. Necesita un lienzo vacío, donde debe renderizar el SVG con el tamaño personalizado, luego puede exportarlo a PNG o JPEG:

<canvas id="myOutputCanvas"></canvas>

<script>
    // 1. Obtenga el elemento de lienzo y acceda a su contexto
    let canvas = document.getElementById('myOutputCanvas');
    let ctx = canvas.getContext("2d");

    // 2. Declare el nuevo ancho de la imagen que desea generar en píxeles
    // e.g crea una imagen de 1000 píxeles de ancho a partir del SVG dado
    // nota: la altura se calcula automáticamente para conservar la relación de aspecto
    let newWidth = 1000;

    // 3. Crea un elemento de imagen para cargar el SVG
    let img = new Image();

    // 4. Una vez que se procesa SVGDataURL en el elemento Image
    // proceda a renderizarlo en el canvas vacío que contendrá
    // la misma imagen, pero en el tamaño que deseas, conservando
    // los detalles de la cadena de SVG
    img.onload = function() {
        // Declarar las dimensiones iniciales de la imagen.
        let originalWidth = img.width;
        let originalHeight = img.height;

        // Declare el nuevo ancho de la imagen
        // Y calcula la nueva altura para conservar la relación de aspecto
        img.width = newWidth;
        img.height = (originalHeight / originalWidth) * newWidth;

        // Establecer las dimensiones del lienzo a las nuevas dimensiones de la imagen
        canvas.width = img.width;
        canvas.height = img.height;

        // Renderizar imagen en Canvas
        ctx.drawImage(img, 0, 0, img.width, img.height); 

         // ¡Eso es TODO! Si tu canvas es visible, ahora puedes ver
         // ¡la imagen del nuevo tamaño!
         // Exportar el lienzo a blob
         // Puedes exportar esto ahora como una URL de datos base64 o un blob
        // canvas.toBlob(function(blob){
        //  haz algo con el blob
        //}, "image/png", 1);
    };

    // Cargar la DataURL de la SVG
    img.src = "data:image/svg+xml;charset=utf-8,[Los datos sin formato codificados en URL de SVG deben estar aquí, reemplácelos con los datos del paso n. ° 1]";
</script>

Puedes ver un ejemplo en vivo de esta implementación en el siguiente violín, donde simplemente puede proporcionar su cadena SVG en un área de texto, establecer el nuevo ancho de la imagen de salida y exportarlo al formato de imagen que desee:

Que te diviertas❤️!

Esto podria interesarte

Conviertete en un programador más sociable