Chartjs + jsPDF = Blurry image

Tiago São José picture Tiago São José · Jan 20, 2016 · Viewed 8.2k times · Source

I'm having some issues exporting my Charts to PDF.

I have this div

    <div id="chart-area">
    <button type="button" id="btnPrint_" onClick="Print1()">Print</button>
    <?php echo '<h2 id="title">'.$_SESSION['team_name'].'</h2>'; ?>
        <canvas id="myChart" width="800" height="400"></canvas>
        <div id="legend"></div>
    </div>

and I'm creating my chart using ChartJS

$( document ).ready(function(){
    var helpers = Chart.helpers;
    var canvas = document.getElementById('myChart');
    var data = {
        labels: unique_dates,
        datasets: [
            {
                label: "Ticket Count",
                fillColor: "rgba(107, 110, 111, 0.6)",
                strokeColor: "rgba(107, 110, 111, 0.6)",
                highlightFill: "rgba(107, 110, 111, 0.6)",
                highlightStroke: "rgba(151,137,200,1)",
                data: ticket_count
            },
            {
                label: "Subsidy Count",
                fillColor: "rgba(8, 126, 210,0.5)",
                strokeColor: "rgba(8, 126, 210,0.8)",
                highlightFill: "rgba(220,220,220,0.75)",
                highlightStroke: "rgba(220,220,220,1)",
                data: subsidy_count
            }
        ]
    }


  var bar = new Chart(canvas.getContext('2d')).Bar(data, {
  tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>kb",
  animation: true,
});
// 
var legendHolder = document.createElement('div');
legendHolder.innerHTML = bar.generateLegend();

document.getElementById('legend').appendChild(legendHolder.firstChild); 

});

When I click the btnPrint_ Button I want to export my chart as PDF

like this

function Print1() {
            var title = $("#title").text();
            var doc = new jsPDF('l', 'mm',[210, 297]);
           html2canvas($("#myChart"), {
                onrendered: function(canvas) {         
                    var imgData = canvas.toDataURL('image/png',1.0);                  
                    doc.text(130,15,title+" GT Log");
                    doc.addImage(imgData, 'PNG',20,30,0,130); 
                    doc.addHTML(canvas);
                    doc.save(title+'gt_log.pdf');             
                    }       
            });

}

The problem is that my chart is totally blurry in the pdf file.

Any idea how to fix this?

it's the first time that I'm using ChartJS and jsPDF so probably I'm doing something wrong.

Thanks!

Answer

crabbly picture crabbly · Apr 7, 2016

The resolution comes from the Canvas size. The more you increase your Canvas (width and height), the better will be the resolution when downloading your PDF.

However, you probably don't want to increase the canvas size too much, so, one trick you could use is to create a hidden Canvas, with a higher width and height, use it to print the chart and create the PDF, getting a better PDF quality.

Here is a fiddle demonstrating this, with an option to download a PDF created from the original canvas/chart, and another option to download a new PDF from the hidden canvas/chart. You can see how the quality increase quite a bit when comparing both results.

https://jsfiddle.net/crabbly/kL68ey5z/

I don't think this is the best solution, however, it is the only way I could come up to increase the quality of my PDF chart files. I'm currently playing around both libraries, specially how jsPDF treats the w and h arguments when creating the docs.

Also, Chart.js does come with a built in function to extract an image form the chart (.toBase64Image()), however, the quality seems to be worse when I tested.