How to save Chart JS charts as image without black background using blobs and filesaver?
Asked Answered
D

3

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

Here i am using Chart JS(v2.5.0) for rendering charts. When i try to export the charts using Canvas to Blob converter and filesaver.js, i get the black background. So how do i get the image with customized background color(preferably white)?

Distinctly answered 27/4, 2017 at 17:49 Comment(0)
C
21

If you want a customized background color then, you'd have to draw a background with your preferred color, and you can do so, like this ...

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);
    }
});

DEMO

// 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>
Carleycarli answered 27/4, 2017 at 18:28 Comment(4)
Thanks for your help, now the image gets downloaded with custom background & this code seems to be doesn't work in Mozilla and Safari. Is there a chance to even achieve the same over there?Distinctly
@Distinctly I believe its an issue with the fileSaver library, as toBlob method isn't supported in Safari. Though it works in FirefoxStopple
This works well. It bothers me that the code in the beforeDraw plugin gets called for every data point. (Console log it and see for yourself.) But I've tried switching to beforeDatasetDraw and beforeDatasetsDraw and the same code located in either of those event plugins does not have the same effect. I'm also not finding an effective way to implement a run-once flag for the code using a global boolean. So, there's rather a lot of wasted bit motion with this solution, but it does work and is the only thing I've found that does.Elly
Actually that's pretty close to the official docs/Plugin (Scroll down on the page and select the third tab of the code viewer). The difference to register that chart Chart plugin after creation seemed to do the trick.Mackinnon
E
16

As I stated in my comment to the accepted answer, it bothered me that the beforeDraw event causes the fillRect code to get called multiple times. (Once per data point as far as I can see.)

But I couldn't get that approach to work when called on any other event. However, I just took the coding approach described in this answer and plugged it into code registered to run on the afterRender event and it does just what I want: run once and leave the background white.

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://mcmap.net/q/671225/-set-background-color-to-save-canvas-chart
        ctx.globalCompositeOperation = 'destination-over';
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, c.chart.width, c.chart.height);
        ctx.restore();
    }
});

Please visit (and up vote) the linked answer to the other posted question.

Elly answered 27/12, 2018 at 14:30 Comment(0)
U
1

In React, with react-chartjs-2, i was able to set background color of chart like so:

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();
    }
};

And then add the plugin to the chart:

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

Reference to the Docs

To save the chart as an image:

I created a function that uses the toBase64Image function to extract the image. I attached this function to a button to help me download chart image on click of button.

function downloadImage(){
    const link = document.createElement("a");
    link.download = `${chart.name || 'chart'}.jpg`
    link.href = chartRef.current.toBase64Image('image/jpeg', 1);
    link.click();
  }
Ukulele answered 7/4, 2022 at 22:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.