Chartjs + jsPDF =模糊图像

时间:2016-01-20 10:30:10

标签: chart.js jspdf html2canvas

我在将图表导出为PDF时遇到了一些问题。

我有这个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>

我正在使用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); 

});

当我点击 btnPrint _ 按钮时,我想将我的图表导出为PDF

像这样

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

}

问题是我的图表在pdf文件中完全模糊。

知道如何解决这个问题吗?

这是我第一次使用ChartJS和jsPDF,所以我可能做错了。

谢谢!

3 个答案:

答案 0 :(得分:8)

分辨率来自画布大小。增加画布(宽度和高度)越多,下载PDF时的分辨率就越高。

但是,您可能不希望过多地增加画布大小,因此,您可以使用的一个技巧是创建一个具有更高宽度和高度的隐藏画布,使用它来打印图表并创建PDF ,获得更好的PDF质量。

这是一个演示此功能的小提琴,可选择下载从原始画布/图表创建的PDF,以及从隐藏的画布/图表下载新PDF的另一个选项。比较两种结果时,您可以看到质量如何提高。

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

我不认为这是最好的解决方案,但是,这是我提高PDF图表文件质量的唯一方法。我目前正在玩两个库,特别是jsPDF在创建文档时如何处理wh参数。

此外,Chart.js还带有内置功能,可以从图表中提取图像(.toBase64Image()),但是,当我测试时质量似乎更差。

答案 1 :(得分:1)

我一直致力于一个项目尝试使用chartjs生成图形,然后使用Chrome的打印到PDF功能打印它们,我发现chartjs图表看起来很糟糕。在stackoverflow和github上读取各种线程后,我开发了一个对我来说运行良好的解决方案。

在我的特定情况下,我需要固定大小的图形,我不能让它们响应,因为我需要它们正确地适合打印页面。我使用样式标签来设置大小:

<canvas style="width: 300px; height: 300px" />

我发现如果你在图表中设置了response:false然后使用这样的样式标签,Chartjs就不会弄乱图表的大小。使用任何其他方法,如设置宽度或高度(不是样式宽度或高度)或使用css类将无法正确设置它。当我为此设置元素的内联样式标记时,Chartjs似乎才有效。

无论如何,在获得更好的PDF输出方面对我有用的技巧是让Chartjs渲染更大的图表,然后将其缩小到更小的尺寸,以便它正确地适合我的页面。

让我们说出于某种原因,我们想要一个300x300像素的图表,当我们将它打印成PDF时看起来很差。我们需要让Chartjs将此图表绘制成更大的图表,然后将其调整为300x300。在我自己的项目中,我让Chartjs将其绘制为2倍大。因此,对于此示例,我将创建一个600x600的canvas元素,如下所示:

<canvas style="width: 600px; height: 600px;" class="graph" />

同时我有一个“graph”css类,其高度和宽度设置为300px。由于内联样式,图表不会以300px渲染。

然后您可以像往常一样制作图表,但在制作图表的代码行之后,您可以从图表中删除内联样式标记。我发现当你这样做时,chartjs会将图表绘制成更大的图表 尺寸为600x600但随后图表立即调整为300x300。以下是代码的示例:

  

var ctx = canvas.getContext('2d'); var mychart = new Chart(ctx,{....   }); canvas.removeAttribute( “风格”);

canvas.removeAttribute删除内联样式标记,然后删除css类 生效并立即使画布以较小的尺寸重新渲染。没有任何闪光或任何迹象表明这种情况已经发生,但我发现你得到了更高质量的图表。

还有一个问题。您必须为更大的600x600尺寸设计图表,以便使其看起来正确。当您以更大的尺寸绘制图表时,线条和字体不会调整大小,因此一切看起来都很小。我必须手动将我的图表设置为更大的尺寸来设计它,并首先找出图形的良好字体和线条大小,然后在此处执行调整大小的技巧。

我还发现,简单地使用较小尺寸的图表并制作较粗的线条或较大的字体似乎与首先调整所有内容的效果不同,然后将其渲染为较小的尺寸。

答案 2 :(得分:0)

由于几个版本的 Chart.js 有参数 devicePixelRatio。 默认情况下,画布由显示器以 DPI 编号呈现,因此 96 或 Retina - 不适合打印输出,但适合屏幕。

如果增加此值,则会创建更多像素。扩展该值,以便您可以将打印质量的图表导出为 Base64 图像。该值不影响图表在监视器上的显示。

就我而言,我将值设置为 1.5。

clientintents = discord.Intents.all()

bot = commands.Bot(command_prefix='b?', intents=clientintents)

文档:https://www.chartjs.org/docs/3.0.2/configuration/device-pixel-ratio.html 效果很好......