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)?

user7932844
  • 341
  • 1
  • 4
  • 12

3 Answers3

18

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>
ɢʀᴜɴᴛ
  • 30,077
  • 15
  • 102
  • 104
  • 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? – user7932844 Apr 29 '17 at 08:01
  • @user7932844 I believe its an issue with the *fileSaver* library, as `toBlob` method isn't supported in Safari. Though it works in Firefox – ɢʀᴜɴᴛ Apr 29 '17 at 08:09
  • Works beautifully. Thanks! – Mike Carpenter Jul 22 '18 at 01:46
  • 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. – Anne Gunn Dec 27 '18 at 14:12
13

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: https://stackoverflow.com/a/50126796/165164 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://stackoverflow.com/a/50126796/165164
        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.

Anne Gunn
  • 2,279
  • 1
  • 28
  • 39
0

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]} />

Docs reference: https://www.chartjs.org/docs/latest/configuration/canvas-background.html#color

TO SAVE CHART AS 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();
  }
Dev_Ose
  • 31
  • 4