使用d3.js将SVG添加到Canvas

use*_*804 14 javascript select svg node.js d3.js

有没有人在创建d3.js可视化时尝试使用svg来绘制库?我已经尝试使用canvg.js和d3.js将svg从android 2.3应用程序webview中转换为canvas,但是当我调用时:

svg.selectAll(".axis")
    .data(d3.range(angle.domain()[1]))
    .enter().append("g")
    .attr("class", "axis")
    .attr("transform", function(d) { return "rotate(" + angle(d) * 180 / Math.PI + ")"; })
    .call(d3.svg.axis()
        .scale(radius.copy().range([-5, -outerRadius]))
        .ticks(5)
        .orient("left"))
    .append("text")
    .attr("y", 
        function (d) {
            if (window.innerWidth < 455){
                console.log("innerWidth less than 455: ",window.innerWidth);
                return -(window.innerHeight * .33);
            }
            else {
                console.log("innerWidth greater than 455: ",window.innerWidth);
                return -(window.innerHeight * .33);
            }
        })
    .attr("dy", ".71em")
    .attr("text-anchor", "middle")
    .text(function(d, i) { return capitalMeta[i]; })
    .attr("style","font-size:12px;");
Run Code Online (Sandbox Code Playgroud)

我收到错误:Uncaught TypeError:无法调用setPropertynull的方法http://mbostock.github.com/d3/d3.js?2.5.0:1707

是某种无头浏览器应用程序,还是服务器端js解析器?有没有人遇到过这个?

ace*_*ace 17

这里有一种方法可以将svg写入canvas(然后将结果保存为png或其他):

// Create an export button
d3.select("body")
    .append("button")
    .html("Export")
    .on("click",svgToCanvas);

var w = 100, // or whatever your svg width is
    h = 100;

// Create the export function - this will just export 
// the first svg element it finds
function svgToCanvas(){
    // Select the first svg element
    var svg = d3.select("svg")[0][0],
        img = new Image(),
        serializer = new XMLSerializer(),
        svgStr = serializer.serializeToString(svg);

    img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr);

    // You could also use the actual string without base64 encoding it:
    //img.src = "data:image/svg+xml;utf8," + svgStr;

    var canvas = document.createElement("canvas");
    document.body.appendChild(canvas);

    canvas.width = w;
    canvas.height = h;
    canvas.getContext("2d").drawImage(img,0,0,w,h);
    // Now save as png or whatever
};
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!我还在下面添加了一个解决方案(基于您的解决方案),该解决方案从外部 CSS 样式表中提取样式。 (2认同)

Con*_*ino 7

@ace的答案非常好,但它不处理外部CSS样式表的情况.下面的示例将自动为生成的图像设置原始SVG外观的样式,即使它是从单独的样式表中提取样式.

// when called, will open a new tab with the SVG
// which can then be right-clicked and 'save as...'
function saveSVG(){

    // get styles from all required stylesheets
    // http://www.coffeegnome.net/converting-svg-to-png-with-canvg/
    var style = "\n";
    var requiredSheets = ['phylogram_d3.css', 'open_sans.css']; // list of required CSS
    for (var i=0; i<document.styleSheets.length; i++) {
        var sheet = document.styleSheets[i];
        if (sheet.href) {
            var sheetName = sheet.href.split('/').pop();
            if (requiredSheets.indexOf(sheetName) != -1) {
                var rules = sheet.rules;
                if (rules) {
                    for (var j=0; j<rules.length; j++) {
                        style += (rules[j].cssText + '\n');
                    }
                }
            }
        }
    }

    var svg = d3.select("svg"),
        img = new Image(),
        serializer = new XMLSerializer(),

    // prepend style to svg
    svg.insert('defs',":first-child")
    d3.select("svg defs")
        .append('style')
        .attr('type','text/css')
        .html(style);


    // generate IMG in new tab
    var svgStr = serializer.serializeToString(svg.node());
    img.src = 'data:image/svg+xml;base64,'+window.btoa(unescape(encodeURIComponent(svgStr)));
    window.open().document.write('<img src="' + img.src + '"/>');
};
Run Code Online (Sandbox Code Playgroud)

并且,要完成,调用该函数的按钮:

// save button
d3.select('body')
    .append("button")
    .on("click",saveSVG)
    .attr('class', 'btn btn-success')
Run Code Online (Sandbox Code Playgroud)


Bio*_*ize 1

你有没有在支持SVG的浏览器上尝试过同样的代码,看看是否是webview的问题?然后尝试使用 canvg 的此示例或使用 DOM 序列化的此示例。对于服务器端渲染,您可以从这个示例开始,了解如何使用 Node.js 将其渲染到画布服务器端。