将 c3.js 折线图导出为 png 图像不起作用

Exporting c3.js line charts to png images does not work

我正在使用 SVG.toDataURL() 将 c3js 图表导出为 png 图像。将图表导出为 png 可以正常工作。

对于折线图,它们无法正确呈现。例如

  1. 增加了x轴和y轴的宽度。
  2. 线条不正确,而不是线条显示深黑色区域。

jsfiddle

下面是导出png的代码

 function exportImageAsPNG(){
        var svgElements = $("#chart").find('svg');
        var svg ;
        svgElements.each(function() {
            svg = this;
        });
        var img = document.getElementById("fromcanvas");
        svg.toDataURL("image/png", {
            callback: function(data) {
                img.setAttribute("src", data)
            }
        })
    }

当我使用 canvag 库时,同样的事情发生了。

var $container = $('#chart'),
content = $container.html().trim(),
canvas = document.getElementById('svg-canvas');

// Draw svg on canvas
canvg(canvas, content);

// Change img be SVG representation
var theImage = canvas.toDataURL('image/png');

$("#hiddenPng").attr('href', theImage);
$("#hiddenPng span").trigger("click");

问题是导出器函数在执行导出时仅考虑内联 CSS 样式。换句话说,出口商正在失去对 C3 的 css 设置的跟踪,因此你的图表在出口之前看起来就像这个家伙的权利

https://github.com/c3js/c3/issues/356

最重要的是,黑色三角形是由某些特定 .c3 元素的 fill 属性 引起的。 c3.css 默认将这些设置为 none,但您的出口商不知道。

参见:

并且,如果您从 c3.min.css...

手动关闭 fill 属性

您需要以某种方式将这些特定元素的 fill CSS 属性 设置为内联 CSS(如 ),然后再导出

这里有一个快速的 plainJS 修复方法,如图所示在 genChart();exportImageAsPNG(); 之间添加这些行以解决您的问题。

    genChart();
    var nodeList = document.getElementById('chart').querySelector('svg').querySelectorAll('.c3-chart path');
    var nodeList2 = document.getElementById('chart').querySelector('svg').querySelectorAll('.c3-axis path');
    var nodeList3 = document.getElementById('chart').querySelector('svg').querySelectorAll('.c3 line');
    var line_graph = Array.from(nodeList);
    var x_and_y = Array.from(nodeList2).concat(Array.from(nodeList3));
    line_graph.forEach(function(element){
        element.style.fill = "none";
    })
    x_and_y.forEach(function(element){
        element.style.fill = "none";
        element.style.stroke = "black";
    })
    exportImageAsPNG();

JSFiddle: https://jsfiddle.net/vtange/vajs3cmf/

可能有点晚了,但我希望这个解决方案对未来的开发者有所帮助:

  • 上面经过验证的解决方案不适用于 Barchart 和其他人
  • 所以,基于同样的原则,我做了以下工作,使导出适用于每种图表类型。这里有一些例子:

假设我们在 html 中有这个,并且图表已经用 c3:

生成
<div id="chartID" class="chart-content"></div>

然后,在我们的 JS 中,这是导出函数:

function exportChartToPng(chartID){
//fix weird back fill
d3.select('#'+chartID).selectAll("path").attr("fill", "none");
//fix no axes
d3.select('#'+chartID).selectAll("path.domain").attr("stroke", "black");
//fix no tick
d3.select('#'+chartID).selectAll(".tick line").attr("stroke", "black");
var svgElement = $('#'+chartID).find('svg')[0];
saveSvgAsPng(svgElement, chartID+'.png');
}

注意:saveSvgAsPng 工具来自 https://github.com/exupero/saveSvgAsPng

对于一直遇到这个问题的人,我得到的这个也许可以帮助你...

var nodeList    = $('svg .c3-chart path.c3-shape.c3-shape.c3-line');
var fillArea    = Array.from(nodeList);

fillArea.forEach(function(element){
  element.style.fill = "none";
})