Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
16
rated 0 times [  21] [ 5]  / answers: 1 / hits: 43278  / 7 Years ago, fri, march 31, 2017, 12:00:00

I have used chart.js to generate a report page that has multiple charts. I need to export this report to PDF. There are many solutions available via search, but I cannot find one which has multiple canvas elements.



The only available solution seems to be to loop through all the images, and recreate the report using the images, and then download that as a pdf.



Is there any simpler/more efficient way to accomplish this?



<body>
<h1> Chart 1 </h1>
<div style=width:800px; height:400px;>
<canvas id=chart_1 width=50 height=50></canvas>
</div>

<h1> Chart 2 </h1>
<div style=width:800px; height:400px;>
<canvas id=chart_2 width=50 height=50></canvas>
</div>

<h1> Chart 3 </h1>
<div style=width:800px; height:400px;>
<canvas id=chart_3 width=50 height=50></canvas>
</div>
</body>

More From » pdf

 Answers
162

Honestly, it seems like the easiest approach would be to just provide a download to PDF link that pops up the browser's print page and instruct to user to select print as pdf.



If that approach doesn't work for you (or your users), then here is a rough way to do it.



Basically, we create a new canvas element that is the size of your report page and incrementally paint the pixels from your existing chart.js canvas charts into the new canvas. Once that is done, then you can use jsPDF to add the new canvas to a pdf document as an image and download the file.



Here is an example implementation that does just that.



$('#downloadPdf').click(function(event) {
// get size of report page
var reportPageHeight = $('#reportPage').innerHeight();
var reportPageWidth = $('#reportPage').innerWidth();

// create a new canvas object that we will populate with all other canvas objects
var pdfCanvas = $('<canvas />').attr({
id: canvaspdf,
width: reportPageWidth,
height: reportPageHeight
});

// keep track canvas position
var pdfctx = $(pdfCanvas)[0].getContext('2d');
var pdfctxX = 0;
var pdfctxY = 0;
var buffer = 100;

// for each chart.js chart
$(canvas).each(function(index) {
// get the chart height/width
var canvasHeight = $(this).innerHeight();
var canvasWidth = $(this).innerWidth();

// draw the chart into the new canvas
pdfctx.drawImage($(this)[0], pdfctxX, pdfctxY, canvasWidth, canvasHeight);
pdfctxX += canvasWidth + buffer;

// our report page is in a grid pattern so replicate that in the new canvas
if (index % 2 === 1) {
pdfctxX = 0;
pdfctxY += canvasHeight + buffer;
}
});

// create new pdf and add our new canvas as an image
var pdf = new jsPDF('l', 'pt', [reportPageWidth, reportPageHeight]);
pdf.addImage($(pdfCanvas)[0], 'PNG', 0, 0);

// download the pdf
pdf.save('filename.pdf');
});


You can see it in action at this codepen.



Now let's talk about some gotchas with this approach. First, you have to control the position of each chart.js canvas in the new canvas object. The only way to do that is to have an understanding of how your report page is structured and implement that same structure. In my example, my charts are in a 2x2 grid and the logic handles this accordingly. If you had a 3x2 grid or something different then you would have to change the positioning logic.



Lastly, the final pdf output file dimensions are much larger than the original chart page (from the web). I think the reason is because my chart container div stretches across the full page. Therefore, you probably want to use a different approach for setting the size of your new canvas.



So long story short, the above example is meant to demonstrate an approach and not be your final solution.



Good luck!


[#58319] Wednesday, March 29, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jadyngraysons

Total Points: 455
Total Questions: 109
Total Answers: 98

Location: Trinidad and Tobago
Member since Fri, May 8, 2020
4 Years ago
jadyngraysons questions
Thu, Apr 23, 20, 00:00, 4 Years ago
Sat, Jan 18, 20, 00:00, 4 Years ago
Tue, Dec 31, 19, 00:00, 4 Years ago
;