繁体   English   中英

带有多个 chart.js 图表的页面到 pdf

[英]Page with multiple chart.js charts to pdf

我使用 chart.js 生成了一个包含多个图表的报告页面。 我需要将此报告导出为 PDF。 通过搜索有很多解决方案可用,但我找不到具有多个画布元素的解决方案。

唯一可用的解决方案似乎是遍历所有图像,并使用图像重新创建报告,然后将其下载为 pdf。

有没有更简单/更有效的方法来实现这一点?

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

老实说,似乎最简单的方法是提供一个“下载到 PDF”链接,该链接会弹出浏览器的打印页面并指示用户选择“打印为 pdf”。

如果这种方法对您(或您的用户)不起作用,那么这里有一个粗略的方法。

基本上,我们创建一个新的canvas元素,它是您的报告页面的大小,并将现有 chart.js canvas图表中的像素逐渐绘制到新的canvas 完成后,您可以使用jsPDF将新画布作为图像添加到 pdf 文档并下载文件。

这是一个可以做到这一点的示例实现。

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

你可以在这个codepen 上看到它的实际效果

现在让我们谈谈这种方法的一些问题。 首先,您必须控制每个 chart.js canvas在新canvas对象中的位置。 做到这一点的唯一方法是了解您的报告页面的结构并实施相同的结构。 在我的示例中,我的图表位于 2x2 网格中,逻辑会相应地处理此问题。 如果你有一个 3x2 的网格或不同的东西,那么你将不得不改变定位逻辑。

最后,最终的 pdf 输出文件尺寸比原始图表页面(来自网络)大得多。 我认为原因是因为我的图表“容器”div 横跨整个页面。 因此,您可能希望使用不同的方法来设置新canvas的大小。

长话短说,上面的例子是为了演示一种方法,而不是你的最终解决方案。

祝你好运!

我在 vanilla javascript 中有一个可行的解决方案(尽管我使用了 ts 类型)并使用了 lib jsPdf,其中每个 pdf 页面都需要一个绘图:

let index = 1;
// create new pdf object
// if don't choose compress as true you will end up with a large pdf file
let pdf = new jsPDF({
  orientation: 'landscape',
  unit: 'px',
  format: 'a4',
  compress: true,
})
// search for the html element(s) you need
const canvas = document.querySelectorAll("canvas");
// here my size are in pixels since I configured that in the obj instance
let pageWidth = 400; 
let pageHeight = 400;
let index = 1;
// traverse the array of canvas 
canvas.forEach( (canva:HTMLCanvasElement) => {

  // I added some options among others I added the type of the compression
  // method: FAST
  pdf.addImage(canva, 'PNG', 10, 10, pageWidth, pageHeight, `img${index}`, "FAST");
  // so as to not end up with an extra pdf page at the end of the iteration
  if (index < canvas.length) {
    pdf.addPage();
  }
  index++;
});

// download the pdf
pdf.save('Reporte.pdf');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM