chattago2002
chattago2002

Reputation: 89

Get chart image but without rendering chart

I'm using react-chartjs-2 but I need to get chart only as image, without rendering it. I can't render it because I need to print the image inside a PDF document (react-pdf); if I put the chart component inside Document component (from react-pdf) I receive errors.

I tried to create inside a constant but seems not to work (neither log inside onComplete callback is printed).

const options = {
...
animation: {
onComplete: function(data) {
console.log("complete")
}
}
...
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const chart = new Chart(ctx, {
    type: 'radar',
    options: options,
    data: data
});
console.log(chart.toBase64Image());

I search in Github repo and official website for a specific hook or something else but with no success. Is there a way to get chart image with no render?

Upvotes: 2

Views: 49

Answers (2)

kikon
kikon

Reputation: 8495

You don't get an image for the chart because the canvas has no width or height (check canvas.offsetWidth, canvas.offsetHeight), nor can it have one until you insert it into the DOM.

To get an image without inserting the chart into the DOM, you may use an OffscreenCanvas. With that, set animation: false for the chart, and get the data url using the OffscreenCanvas procedure, not chart.toBase64Image.

Demo snippet (image inserted into the DOM for verification)

const canvas = new OffscreenCanvas(300, 300);
const chart = new Chart(canvas.getContext('2d'), {
   type: 'radar',
   data: {
      labels: ['January', 'February', 'March', 'April', 'May', 'June'],
      datasets: [{
         label: 'Dataset 1',
         data: Array.from({length: 6}, () => Math.random() * 10 + 5),
         backgroundColor: 'rgba(221,84,112,0.4)',
         borderColor: 'rgb(221,84,112)',
      }, {
         label: 'Dataset 2',
         data: Array.from({length: 6}, () => Math.random() * 10 + 5),
         backgroundColor: 'rgba(84,112,221,0.4)',
         borderColor: 'rgb(84,112,221)',
      }]
      
   },
   options: {
      responsive: false,
      animation: false
   }
});

(async () => {
   const blob = await canvas.convertToBlob();
   const dataURL = await new Promise(resolve => {
      const fr = new FileReader();
      fr.onload = function(e){resolve(e.target.result);}
      fr.readAsDataURL(blob);
   });
   
   console.log(dataURL);
   // for verification
   const img = new Image();
   img.src = dataURL;
   document.body.appendChild(img)
})();
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Upvotes: 2

Akshay Kumar
Akshay Kumar

Reputation: 1035

I think you need to take this step by step. react-pdf might not support custom components like charts but it can render images. Try converting your chart into an image first.

    canvas = await html2canvas(chartRef),
    data = canvas.toDataURL('image/jpg')

once you have a url for image, you can use it with react-pdf.

Upvotes: 0

Related Questions