使用canvg将SVG转换为Canvas时不遵守CSS。

3
我正在尝试将SVG转换为画布以获取PNG,除了CSS定位外,一切都很顺利。请参见这个jsfiddle,您可以看到顶部部分是SVG。我正在使用canvg在画布元素上呈现SVG。这两个SVG重叠在一起,一个是100%大小,另一个是80%。我正在使用Raphael渲染它们。我已经尝试过像各种地方建议的插入内联样式:
<style type='text/css'>![CDATA[svg{ margin: 0 auto; }]]></style>

然而,canvg只返回:
Cannot read property 'split' of undefined

我需要画布与SVG完全相同。
*注意,将两者都更改为100%大小并更改圆的半径不是选项,这只是一个简化的版本作为演示。
2个回答

5

虽然不是最理想的解决方案,但一个选项是在渲染之前将所有样式内联处理。以下是我在这个项目上处理同样问题时使用的方法:

function inlineAllStyles() {
    var svg_style, selector, cssText;

    for (var i = 0; i <= document.styleSheets.length - 1; i++) {
        //loop through your stylesheets
        if (document.styleSheets[i].href && document.styleSheets[i].href.indexOf('style.css') != -1) {
            //pull out the styles from the one you want to use
            if (document.styleSheets[i].rules != undefined) {
                svg_style = document.styleSheets[i].rules
            } else {
                svg_style = document.styleSheets[i].cssRules
            }
        }
    }

    if (svg_style != null && svg_style != undefined) {
        for (var i = 0; i < svg_style.length; i++) {
            if (svg_style[i].type == 1) {

                selector = svg_style[i].selectorText;

                styles = makeStyleObject(svg_style[i]);

                // Apply the style directly to the elements that match the selctor
                // (this requires to not have to deal with selector parsing)
                d3.selectAll(selector).style(styles)
            }
        };
    }
}

 function makeStyleObject(rule) {
    var styleDec = rule.style;
    var output = {};
    var s;

    for (s = 0; s < styleDec.length; s++) {
        output[styleDec[s]] = styleDec[styleDec[s]];
        if(styleDec[styleDec[s]] === undefined) {
            //firefox being firefoxy
            output[styleDec[s]] = styleDec.getPropertyValue(styleDec[s])
        }
    }

    return output;
}

inlineAllStyles()

0

如果你的CSS规则不是太复杂,你可以按照以下步骤操作:

  1. 读取包含所有CSS规则的.css文件。如果需要,您可以使用不同的CSS文件并将其放置在服务器上,仅供此目的使用。

    function readTextFile(file) {
        var rawFile = new XMLHttpRequest();
        var allText = '';
        rawFile.open("GET", file, false);
        rawFile.onreadystatechange = function () {
            if(rawFile.readyState === 4) {
                if(rawFile.status === 200 || rawFile.status == 0) {
                    allText = rawFile.responseText;
                }
            }
        };
        rawFile.send(null);
        return allText;
    }
    
    var svg_style = readTextFile(base_url + '/css/svg_sm_dashboard.css');
    
  2. 现在将样式应用于所有SVG元素

    var all_style = svg_style.replace(/\r?\n|\r/g,'').split('}');
    all_style.forEach(function(el) {
        if (el.trim() != '') {
            var full_rule_string = el.split('{');
            var selector = full_rule_string[0].trim();
            var all_rule = full_rule_string[1].split(';');
            all_rule.forEach(function (elem) {
                if (elem.trim() != '') {
                    var attr_value = elem.split(':');
                    d3.selectAll(selector).style(attr_value[0].trim() + '', attr_value[1].trim() + '');
                }
           });
       }
    });
    
  3. 现在使用canvg进行转换

    $('body').after('<canvas id="sm_canvas" style="display=none;"></canvas>');
    var canvas = document.getElementById('sm_canvas');
    canvg(canvas, $("<div>").append($('svg').clone()).html());
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接