jsPDF +キャンバス:ロシア語の複数ページの表のPDFへのエクスポート

PDF生成...このトピックは新しいものではありませんが、微妙な点に出くわすことがあり、最終的には自転車建設の困難な道を歩むことになります。 今日は、そのような自転車を開発する方法を説明します。

PDFでレポートを生成する必要がありました。 いくつかの理由から、クライアント側でこれを行うことにしました。 簡単な検索で、 jsPDFpdfmakeを選択できました 。 最初に停止しました。 そして今、もっと...



そもそも、jsPDFは素晴らしいことですが、このプロジェクトのドキュメンテーションはとんでもない所にあると言いたいです。
精神的に準備ができていない人がわいせつな言葉を誓う欲求を引き起こすこと。 Symfonyのドキュメントを思い出します。それを読んでから、「how?」という質問でGoogleを検索します(またはソースに移動します)。

このライブラリによって私に投げかけられた最初の落とし穴は、ロシア語(および全体としてUTF-8 、私が理解できる限り)のサポートの欠如でした

(それどころか、pdfmakeはUTF-8で動作しますが、すぐにこのライブラリの使用を拒否しました。)

検索して実験した後、レンダリングにキャンバスを使用することにしました。 ただし、ここで2つ目の落とし穴が見つかりました。canvasは現在の画面のみをキャプチャし、巨大なテーブルは空のシートのセットとして(または経済的に)保存されています。

スクリプトでテーブルを壊し、一時的なコンテナに入れ、それからキャンバスを作成し、再作成する必要がありました。 結果は次のとおりです。
app.factory("PDF", function() { return { tableToPDF: function() { var pdf = new jsPDF('p', 'pt', 'a4'); var rows = $("table").find("tr"); var pdfContainer = $(".tmp-pdf-container"); var pdfInternals = pdf.internal; var pdfPageSize = pdfInternals.pageSize; var pdfPageWidth = pdfPageSize.width; var pdfPageHeight = pdfPageSize.height; var partialSize = 10; var contentSize = 0; var marginTop = 20; var index = 0; //     partialSize  var generatePartial = function() { var partial = ""; rows.each(function(i, row) { if (i >= index && i <= partialSize) { partial += "<tr>" + $(this).html() + "</tr>"; index++; if (index >= partialSize) { partialSize += 10; return false; } } }); return partial; } var processCanvases = function() { if (index >= rows.length) { pdfContainer.html(""); //pdf.output("datauri"); pdf.save("TEST.pdf"); return; } var partial = generatePartial(); // generate table with that rows var table = $(document.createElement("table")); table.append("<tbody>" + partial + "</tbody>"); // insert table to temporary div pdfContainer.html("<table class='table table-fixed-width table-condensed'>" + table.html() + "</table>"); // hide unnecessary columns pdfContainer.find(".non-printable").css("display", "none"); // generate canvas from that table html2canvas(pdfContainer, {background: "white"}).then(function(canvas) { // contentSize   //   4     partial, //  ,           if (contentSize < 2) { contentSize ++; pdf.addImage(canvas, "jpeg", 20, marginTop, pdfPageWidth-40, 0); //      //   0.01 ,  0.05,   ,     marginTop += canvas.height/ (canvas.width / pdfPageHeight + (pdfPageWidth / pdfPageHeight) - 0.05); } else { pdf.addImage(canvas, "jpeg", 20, marginTop, pdfPageWidth-40, 0); //   ,         if (index < rows.length) { pdf.addPage(); } contentSize = 0; marginTop = 0; } // next iteration processCanvases(); }); } processCanvases(); } } }); 


 <div class="tmp-pdf-container" style="position: absolute; left: -9999; width: 1000px"></div> 


PNG形式についても言及したいと思います。 物事は良い(私が知る限り、画像/ jpegとは異なり、古いブラウザでサポートされています)が、PDFは時々重いです。 さらに、大規模なレポートでは、ブラウザが必ず落ちることが保証されています。具体的には、私のクロームはエラーウィンドウを投げ、FFは通常それ自体とシステムを積み重ねたため、大ハンマーのみを保存しました。

JPEGで生成し始めたとき、私はアフロの黒い背景を得ました。 JPEG透明度がアフロを黒にすることが判明しました。

また、html2canvasはコードからキャンバスを生成する方法を知らないため、一時的な要素を作成する必要があります。 さらに、彼は目に見えない要素を描画しません。 stackoverflowのどこかで、iframeがアドバイスされました。私は個人的にdivを追加しました。絶対位置と左端:-9999で、干渉しないようにしました(画面上のプランカーでは取得できませんでした)

テーブルをスライスするのも困難です:列が異なります。 これを修正し、次のスタイルを追加しました。
  .table-fixed-width { table-layout: fixed; } 


次に例を示します。plnkr.co / edit / r3BaDwHpK5H9giwpqrBb

結論:バイクを書くことは必ずしも悪いことではありません。 多くの場合、これは新しいことを学ぶのに役立ちます。 ただし、これは習慣になるべきではないので、少なくとも少し突き出すためには、常にドックを読む必要があります。

この記事が誰かのお役に立てば幸いです。また、あなたのアドバイスやアイデアを聞いてみたいです。

Source: https://habr.com/ru/post/J278047/


All Articles