如何使用Blob和FileSaver将Chart JS图表保存为图片而不带黑色背景?

11
$("#NoBidsChart").get(0).toBlob(function(value) {
    saveAs(value, "Summary.jpg");
});

我正在使用Chart JS(v2.5.0)来渲染图表。当我尝试使用Canvas to Blob转换器和filesaver.js导出图表时,背景会变成黑色。那么我该如何获得带有自定义背景颜色(最好是白色)的图像呢?

3个回答

21

如果你想要自定义背景色,那么你需要用自己喜欢的颜色绘制一个背景,具体方法如下...

var backgroundColor = 'white';
Chart.plugins.register({
    beforeDraw: function(c) {
        var ctx = c.chart.ctx;
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(0, 0, c.chart.width, c.chart.height);
    }
});

演示

// draw background
var backgroundColor = 'white';
Chart.plugins.register({
    beforeDraw: function(c) {
        var ctx = c.chart.ctx;
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(0, 0, c.chart.width, c.chart.height);
    }
});

// chart
var canvas = $('#NoBidsChart').get(0);
var myChart = new Chart(canvas, {
    type: 'line',
    data: {
        labels: [1, 2, 3, 4, 5],
        datasets: [{
            label: 'Line Chart',
            data: [1, 2, 3, 4, 5],
            backgroundColor: 'rgba(255, 0, 0, 0.2)',
            borderColor: 'rgba(255, 0, 0, 0.5)',
            pointBackgroundColor: 'black'
        }]
    }
});

// save as image
$('#save').click(function() {
    canvas.toBlob(function(blob) {
        saveAs(blob, "pretty image.png");
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<button id="save">Save</button>
<canvas id="NoBidsChart"></canvas>


感谢您的帮助,现在图像已经下载并带有自定义背景。但是这段代码似乎在Mozilla和Safari中不起作用。是否有可能在那里实现相同的效果? - user7932844
@user7932844 我认为这是 fileSaver 库的问题,因为 toBlob 方法在 Safari 中不受支持。虽然它在 Firefox 中可以工作。 - ɢʀᴜɴᴛ
1
这个很好用。让我困扰的是beforeDraw插件中的代码会为每个数据点调用一次。(自己记录控制台日志看看吧。)但我尝试切换到beforeDatasetDraw和beforeDatasetsDraw,位于这些事件插件中的相同代码没有相同的效果。我也没有找到一个有效的方法来使用全局布尔值实现一次运行标志的代码。所以,这个解决方案有很多浪费的位运动,但它确实有效,而且是我发现的唯一有效的东西。 - Anne Gunn
实际上这非常接近官方文档/插件(在页面上向下滚动并选择代码查看器的第三个选项卡)。在创建后注册该图表插件似乎是解决问题的关键。 - Cadoiz

16

正如我在接受的答案评论中所述,beforeDraw事件使得fillRect代码被多次调用(据我所见,每个数据点一次)让我感到不安。

但是,我无法通过在任何其他事件上调用来使该方法生效。 然而,我刚刚采用了此答案中描述的编码方法,并将其插入到在afterRender事件上注册的代码中,它确实做到了我想要的:只运行一次并保留白色背景。

Chart.plugins.register({
    afterRender: function(c) {
        console.log("afterRender called");
        var ctx = c.chart.ctx;
        ctx.save();
        // This line is apparently essential to getting the
        // fill to go behind the drawn graph, not on top of it.
        // Technique is taken from:
        // https://dev59.com/h6vka4cB1Zd3GeqPmgSX#50126796
        ctx.globalCompositeOperation = 'destination-over';
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, c.chart.width, c.chart.height);
        ctx.restore();
    }
});
请访问(并投票支持)另一个已发布问题的相关答案

1
在React中,使用react-chartjs-2,我可以像这样设置图表的背景颜色:
const plugin = {
    beforeDraw: (chartCtx) => {
      const ctx = chartCtx.canvas.getContext('2d');
      ctx.save();
      ctx.globalCompositeOperation = 'destination-over';
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, chartCtx.width, chartCtx.height);
      ctx.restore();
    }
};

然后将插件添加到图表中:

<Line ref={chartRef} data={chartData} options={options} plugins={[plugin]} />

文档参考

将图表保存为图片:

我创建了一个函数,使用toBase64Image函数提取图像。我将此函数附加到按钮上,以便在单击按钮时下载图表图像。

function downloadImage(){
    const link = document.createElement("a");
    link.download = `${chart.name || 'chart'}.jpg`
    link.href = chartRef.current.toBase64Image('image/jpeg', 1);
    link.click();
  }

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