当前位置: 首页 > 知识库问答 >
问题:

包含多个chart.js图表的页面,可转换为pdf格式

周玺
2023-03-14

我已经使用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>

共有2个答案

范华清
2023-03-14

我有一个香草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');

岳枫
2023-03-14

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

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

基本上,我们创建一个新的canvas元素,该元素的大小与您的报告页面相同,并将现有chart.jscanvas图表中的像素增量绘制到新的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');
});

您可以在这个代码笔中看到它的作用。

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

最后,最终的pdf输出文件尺寸比原始图表页面(来自web)大得多。我认为原因在于我的图表“容器”div贯穿了整个页面。因此,您可能希望使用不同的方法来设置新的画布的大小。

长话短说,上述示例旨在演示一种方法,而不是最终解决方案。

祝你好运!

 类似资料:
  • 我有一个docx4j生成的文件,其中包含几个表格、标题,最后还有一个excel生成的曲线图。 我尝试了许多方法,以将此文件转换为PDF,但没有得到任何成功的结果。 带有xsl fo的Docx4j不起作用,docx文件中包含的大部分内容尚未实现,并以红色文本显示为“未实现” 我在Apache POI中使用的代码如下: 我不知道该怎么做才能得到PDF中的图表,有人能告诉我如何继续吗? 提前感谢。

  • 我正在使用,我已经能够获得一个html页面并为该页面生成pdf,但我需要从多个html页面生成一个pdf文档,并用页面分隔。例如:我有,。我需要一份3页的pdf文档,第一页的内容为之类的。。。 这是我的代码,它适用于一个html页面: 是否可以针对多个html页面进行循环,为每个html页面向PdfDocument添加一个新页面,然后仅生成一个pdf,每个html页面生成一个页面? 更新 我一直在

  • 我有一个超文本标记语言的非常简单的表格,其中包含12列。我试图使用iText 5.1.1(Java)将其转换为PDF。 我的问题是,PDF输出中的表格换行了。我的意思是,它显示第一行,但在页面的末尾换行,然后没有换行符或任何东西,它只显示紧接在前一行的最后一个单元格之后的下一行。 如何使iText的HtmlWorker “nowrap”我的表格,即在PDF中显示一行? 顺便说一句,我仍然希望单元格

  • 我想使用FlyingSaucer将一个包含阿拉伯字符的HTML页面转换为PDF文件,但生成的PDF不包含组合字符,并向后打印输出。 HTML: null null Java摘录: 我怎样做才能得到正确的结果?

  • 我用 1 个类的不同数据填充我的表视图没有问题。但是它对多个类的我不起作用。知道如何解决这个问题吗?我已经在stackoverflow上查看了类似的问题。但他们都帮不了我。如果您对“回调”类有任何建议,请为我提供完整的导入,因为那里有几个回调类。 进一步的问题:如何在表格单元格的哈希集中显示实例的某个属性。所以我在我的 TaskControl 类中有一个 HashSet。在该HashSet中,有类