web-dev-qa-db-ja.com

複数のchart.jsチャートを含むページを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>
8

正直なところ、最も簡単な方法は、ブラウザの印刷ページをポップアップする「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 で実際の動作を確認できます。

ここで、このアプローチに関するいくつかの落とし穴について話しましょう。まず、新しいcanvasオブジェクト内の各chart.js canvasの位置を制御する必要があります。これを行う唯一の方法は、レポートページの構造を理解し、同じ構造を実装することです。私の例では、チャートは2x2グリッドにあり、ロジックはこれを適切に処理します。 3x2グリッドなどがある場合は、配置ロジックを変更する必要があります。

最後に、最終的なPDF出力ファイルのサイズは、(Webからの)元のチャートページよりもはるかに大きくなります。その理由は、チャートの「コンテナー」のdivがページ全体に広がっているためです。したがって、おそらく新しいcanvasのサイズを設定するために別のアプローチを使用したいと思うでしょう。

要するに、上記の例はアプローチを示すことを目的としており、最終的なソリューションではありません。

幸運を!

16
jordanwillis