JavaScript如何将SVG字符串或节点转换为图像(PNG或JPEG)

2021年11月29日23:36:01 发表评论 555 次浏览

了解如何直接在浏览器中轻松地将普通 SVG 字符串转换为图像。

如何使用 JavaScript 在浏览器中将普通 SVG 字符串或 SVG 节点转换为图像(PNG 或 JPEG)

有很多操作可以在客户端进行,因此你可以节省一些服务器处理能力。本周我需要解决的任务之一是找到将 SVG 字符串转换为任何用户都可以理解的图像格式(PNG 或 JPEG)的最简单方法。

JavaScript如何将SVG字符串转换为图像?在本文中,我将与你分享我使用 Vanilla JavaScript 从浏览器中的任何 SVG 字符串或 SVG Dom 节点创建图像的方法。

1.创建SVGToImage函数

JavaScript将SVG字符串转换为图像的方法?将帮助你将 SVG 转换为图像的功能如下:

/**
 * Simple function that converts a plain SVG string or SVG DOM Node into an image with custom dimensions.
 * 
 * @param {Object} settings The configuration object to override the default settings.
 * @see https://ourcodeworld.com/articles/read/1456/how-to-convert-a-plain-svg-string-or-svg-node-to-an-image-png-or-jpeg-in-the-browser-with-javascript
 * @returns {Promise}
 */
function SVGToImage(settings){
    let _settings = {
        svg: null,
        // Usually all SVG have transparency, so PNG is the way to go by default
        mimetype: "image/png",
        quality: 0.92,
        width: "auto",
        height: "auto",
        outputFormat: "base64"
    };

    // Override default settings
    for (let key in settings) { _settings[key] = settings[key]; }

    return new Promise(function(resolve, reject){
        let svgNode;

        // Create SVG Node if a plain string has been provided
        if(typeof(_settings.svg) == "string"){
            // Create a non-visible node to render the SVG string
            let SVGContainer = document.createElement("div");
            SVGContainer.style.display = "none";
            SVGContainer.innerHTML = _settings.svg;
            svgNode = SVGContainer.firstElementChild;
        }else{
            svgNode = _settings.svg;
        }

        let canvas = document.createElement('canvas');
        let context = canvas.getContext('2d'); 

        let svgXml = new XMLSerializer().serializeToString(svgNode);
        let svgBase64 = "data:image/svg+xml;base64," + btoa(svgXml);

        const image = new Image();

        image.onload = function(){
            let finalWidth, finalHeight;

            // Calculate width if set to auto and the height is specified (to preserve aspect ratio)
            if(_settings.width === "auto" && _settings.height !== "auto"){
                finalWidth = (this.width / this.height) * _settings.height;
            // Use image original width
            }else if(_settings.width === "auto"){
                finalWidth = this.naturalWidth;
            // Use custom width
            }else{
                finalWidth = _settings.width;
            }

            // Calculate height if set to auto and the width is specified (to preserve aspect ratio)
            if(_settings.height === "auto" && _settings.width !== "auto"){
                finalHeight = (this.height / this.width) * _settings.width;
            // Use image original height
            }else if(_settings.height === "auto"){
                finalHeight = this.naturalHeight;
            // Use custom height
            }else{
                finalHeight = _settings.height;
            }

            // Define the canvas intrinsic size
            canvas.width = finalWidth;
            canvas.height = finalHeight;

            // Render image in the canvas
            context.drawImage(this, 0, 0, finalWidth, finalHeight);

            if(_settings.outputFormat == "blob"){
                // Fullfil and Return the Blob image
                canvas.toBlob(function(blob){
                    resolve(blob);
                }, _settings.mimetype, _settings.quality);
            }else{
                // Fullfil and Return the Base64 image
                resolve(canvas.toDataURL(_settings.mimetype, _settings.quality));
            }
        };

        // Load the SVG in Base64 to the image
        image.src = svgBase64;
    });
}

SVGToImage 接收一个支持以下属性的对象作为第一个参数:

  • svg: 一个 SVG DOM 节点或带有 SVG 数据的纯字符串。这将被转换为图像。
  • mimetype:图像的输出 mime 类型,它可以是image/pngimage/jpegimage/webp在 chrome 中也可以)。默认情况下,它使用 PNG 格式,像往常一样,每个 SVG 图像都有透明度。
  • width:将创建的图像的输出宽度(以像素为单位)。默认情况下,它采用 SVG 图像的宽度(自动)。如果你为图像提供自定义高度并且宽度设置为自动,则会自动计算宽度以保留 SVG 的纵横比。
  • height:将创建的图像的输出高度(以像素为单位)。默认情况下,它采用 SVG 图像的高度(自动)。如果你为图像提供自定义宽度并且高度设置为自动,则将自动计算高度以保留 SVG 的纵横比。
  • quality:一个介于 0 和 1 之间的数字,表示用于使用有损压缩的图像格式(例如image/jpeg和 )的图像质量image/webp。如果此参数是其他任何参数,则使用图像质量的默认值。默认值为 0.92。其他参数被忽略。
  • outputFormat: 图像的导出格式,可以是base64DataURL 或blob.

2. 从一个普通的 SVG 字符串创建一个图像

JavaScript如何将SVG字符串转换为图像?例如,如果你想从一个普通的 SVG 字符串创建一个图像,你可以使用这样的函数:

SVGToImage({
    // 1. Provide the SVG
    svg: `<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> <path d="M1585 1215q-39 125-123 250-129 196-257 196-49 0-140-32-86-32-151-32-61 0-142 33-81 34-132 34-152 0-301-259-147-261-147-503 0-228 113-374 113-144 284-144 72 0 177 30 104 30 138 30 45 0 143-34 102-34 173-34 119 0 213 65 52 36 104 100-79 67-114 118-65 94-65 207 0 124 69 223t158 126zm-376-1173q0 61-29 136-30 75-93 138-54 54-108 72-37 11-104 17 3-149 78-257 74-107 250-148 1 3 2.5 11t2.5 11q0 4 .5 10t.5 10z"/> </svg>`,
    // 2. Provide the format of the output image
    mimetype: "image/png",
    // 3. Provide the dimensions of the image if you want a specific size.
    //  - if they remain in auto, the width and height attribute of the svg will be used
    //  - You can provide a single dimension and the other one will be automatically calculated
    // width: "auto",
    // height: "auto",
    width: 500,
    height: 500,
    // 4. Specify the quality of the image
    quality: 1,
    // 5. Define the format of the output (base64 or blob)
    outputFormat: "base64"
}).then(function(outputData){
    // If using base64 (outputs a DataURL)
    //  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0...
    // Or with Blob (Blob)
    //  Blob {size: 14353, type: "image/png"}
    console.log(outputData);
}).catch(function(err){
    // Log any error
    console.log(err);
});

3. 从 SVG Dom 元素创建图像

JavaScript将SVG字符串转换为图像的方法?如果你想直接转换文档中的 DOM 元素而不是普通字符串,你可以简单地选择它并在相同的 SVG 属性中提供它:

<svg id="my-svg" width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
    <path d="M1585 1215q-39 125-123 250-129 196-257 196-49 0-140-32-86-32-151-32-61 0-142 33-81 34-132 34-152 0-301-259-147-261-147-503 0-228 113-374 113-144 284-144 72 0 177 30 104 30 138 30 45 0 143-34 102-34 173-34 119 0 213 65 52 36 104 100-79 67-114 118-65 94-65 207 0 124 69 223t158 126zm-376-1173q0 61-29 136-30 75-93 138-54 54-108 72-37 11-104 17 3-149 78-257 74-107 250-148 1 3 2.5 11t2.5 11q0 4 .5 10t.5 10z"/>
</svg>

<script>
    SVGToImage({
        // 1. Provide the SVG DOM element
        svg: document.getElementById("my-svg"),
        // 2. Provide the format of the output image
        mimetype: "image/png",
        // 3. Provide the dimensions of the image if you want a specific size.
        //  - if they remain in auto, the width and height attribute of the svg will be used
        //  - You can provide a single dimension and the other one will be automatically calculated
        // width: "auto",
        // height: "auto",
        width: 500,
        height: 500,
        // 4. Specify the quality of the image
        quality: 1,
        // 5. Define the format of the output (base64 or blob)
        outputFormat: "base64"
    }).then(function(outputData){
        // If using base64 (outputs a DataURL)
        //  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0...
        // Or with Blob (Blob)
        //  Blob {size: 14353, type: "image/png"}
        console.log(outputData);
    }).catch(function(err){
        // Log any error
        console.log(err);
    });
</script>

现场演示

你可以在以下小提琴中看到此功能如何工作的实时预览,只需在 中提供你自己的 SVGtextarea并提交表单以在文档中附加图像的 PNG 版本:

快乐编码❤️!

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: