Javascript:如何将包含嵌入图像的SVG导出到PNG?

时间:2018-06-07 15:04:56

标签: javascript svg export png

我写了一些Javascript代码,允许我的Web应用程序将SVG导出到PNG,但问题是嵌入的图像不包含在导出的PNG文件中。

这是我的代码:

var svgString;

// Main download function
function download() {
    var exportResolution = 2; // TODO Changeble resolution
    var exportSVG = document.getElementById("canvas").cloneNode(true); // avoids having to reset everything afterward
    // grab its inner content BoundingBox
    var bb = document.getElementById("canvas").getBBox();
    // update its viewBox so it displays all its inner content
    exportSVG.setAttribute('viewBox', bb.x + ' ' + bb.y + ' ' + bb.width + ' ' + bb.height);
    exportSVG.setAttribute('width', bb.width);
    exportSVG.setAttribute('height', bb.height);
    exportSVG.style.fontFamily = "lato";
    exportSVG.style.background = "none"; // TODO without and with background
    svgString = getSVGString(exportSVG);
    console.log(exportSVG.getBBox().width + " / " + exportSVG.getBBox().height);
    svgStringToImage(svgString, bb.width * exportResolution, bb.height * exportResolution, 'png', save); // passes Blob and filesize String to the callback
    console.log("svg export code loaded");
}

function save(dataBlob, filesize) {
    saveAs(dataBlob, 'Example File Name'); // FileSaver.js function, TODO change to document name
}

// Below are the functions that handle actual exporting:
function getSVGString(svgNode) {
    svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
    var cssStyleText = getCSSStyles(svgNode);
    appendCSS(cssStyleText, svgNode);
    var serializer = new XMLSerializer();
    var svgString = serializer.serializeToString(svgNode);
    svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
    svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix
    return svgString;

    function getCSSStyles(parentElement) {
        var selectorTextArr = [];
        // Add Parent element Id and Classes to the list
        selectorTextArr.push('#' + parentElement.id);
        for (var c = 0; c < parentElement.classList.length; c++)
            if (!contains('.' + parentElement.classList[c], selectorTextArr))
                selectorTextArr.push('.' + parentElement.classList[c]);
        // Add Children element Ids and Classes to the list
        var nodes = parentElement.getElementsByTagName("*");
        for (var i = 0; i < nodes.length; i++) {
            var id = nodes[i].id;
            if (!contains('#' + id, selectorTextArr))
                selectorTextArr.push('#' + id);
            var classes = nodes[i].classList;
            for (var c = 0; c < classes.length; c++)
                if (!contains('.' + classes[c], selectorTextArr))
                    selectorTextArr.push('.' + classes[c]);
        }
        // Extract CSS Rules
        var extractedCSSText = "";
        for (var i = 0; i < document.styleSheets.length; i++) {
            var s = document.styleSheets[i];

            try {
                if (!s.cssRules) continue;
            } catch (e) {
                if (e.name !== 'SecurityError') throw e; // for Firefox
                continue;
            }
            var cssRules = s.cssRules;
            for (var r = 0; r < cssRules.length; r++) {
                if (contains(cssRules[r].selectorText, selectorTextArr))
                    extractedCSSText += cssRules[r].cssText;
            }
        }
        return extractedCSSText;

        function contains(str, arr) {
            return arr.indexOf(str) === -1 ? false : true;
        }
    }

    function appendCSS(cssText, element) {
        var styleElement = document.createElement("style");
        styleElement.setAttribute("type", "text/css");
        styleElement.innerHTML = cssText;
        var refNode = element.hasChildNodes() ? element.children[0] : null;
        element.insertBefore(styleElement, refNode);
    }
}

function svgStringToImage(svgString, width, height, format, callback) {
    var format = format ? format : 'png';
    var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString))); // Convert SVG string to data URL
    var canvas = document.createElement("canvas");
    var context = canvas.getContext("2d");
    canvas.width = width;
    canvas.height = height;
    var image = new Image();
    image.onload = function() {
        context.clearRect(0, 0, width, height);
        context.drawImage(image, 0, 0, width, height);
        canvas.toBlob(function(blob) {
            var filesize = Math.round(blob.length / 1024) + ' KB';
            if (callback) callback(blob, filesize);
        });
    };
    image.src = imgsrc;
}

这是我的应用程序中的SVG绘图: enter image description here

您可以看到导出的PNG文件的外观: enter image description here

如您所见,复选框(嵌入的SVG文件)不包含在最终的PNG文件中。

在这种情况下,用于包含嵌入图像的最常用方法是什么?

0 个答案:

没有答案