弁財天

ゴフマン「専門家を信じるのではなく、自分自身で考えて判断せよ」

jsPDFの日本語の文字化けをFabric.jsのレンダリングで回避 update5

Datatablesの調査してるときに JavascriptだけでPDF出力するjsPDFを見つけたのだけど、その続き。

今のところ、このjsPDFもDatatablesのFlashのSWFを使ったPDF出力も日本語が文字化けして潰れてしまって表示できない状況である。

jsPDF-0.9.0rc2/examples/js/basic.jsの

function demoFromHTML() {
    //var pdf = new jsPDF('p', 'in', 'letter'); //←ここ、;は不要。なんだかなー、破壊工作か?
    var pdf = new jsPDF('p', 'in', 'letter')
examplesのコードが壊されてるw

そこに天才が出現。
javascriptでPDF出力(日本語表示)
「jspdf.jsが日本語対応していないので、canvasに日本語で文字書いて、imgとしてpdfに取り込んでいます。」
うは。すっげーw
みつぎーくの学習プリント生成ページ

あぁなるほど、Fabric.jsで canvas に書いたテキストをイメージ化して操作するからね。でもふつう思いつかないって。

JavascriptのcanvasエレメントはHTML5から導入された仕様で「現時点(2011年5月)では、IE9以降、Firefox 1.5以降、Opera 9以降、Safari 1.3以降が 平面(2D)コンテキストをサポートしています。」これ

Fabric.jsのfabric.Image.fromURLが.pngのような画像ファイルじゃなくてPhantomJSのようなブラウザ画面にできればおもろいかもね。

JavaScriptでスクリーンショットが取れるライブラリ「html2canvas」:phpspot開発日誌
html2canvasでブラウザー画面でスクリーンショットが取れるのか。
サンプルで試せる。うはは。できそこないのPhantomJSみたいな。
いろいろ飾りを取っぱらった印刷専用ページなら使えそうだなw

さっそくパクってみた。 スクリーンショット

日本語が文字化けする問題は印刷画面を表示させて、それをhtml2canvasでイメージに変換し、jsPDFに埋め込めばいいのか。まぁ出力が汚いので誰もトライしないだろうけどw やろうと思えば部品はそろっている。

html2canvasでCanvasにイメージをコピーしておいて、
ボタン押した時にjsPDFにaddImage()してみた。
このときFabric.jsは使わなかった。

ここに非表示のcanvasタグ
ここに非表示のimgタグ

おもろい。なんか文字がダブってるとこあるぞw、html2canvasのバグか?

Javascriptだけのロジックでブラウザ画面をイメージとして canvas にレンダリング出力して、その canvas をPDFファイルに埋め込むなんて、いったい誰が想像できただろうか?

<a href="" id="ss_png_href" download="benzaiten_screenshot.jpg">スクリーンショット</a><br />
</p><p>
日本語が文字化けする問題は印刷画面を表示させて、それをhtml2canvasでイメージに変換し、jsPDFに埋め込めばいいのか。まぁ出力が汚いので誰もトライしないだろうけどw やろうと思えば部品はそろっている。
</p><p>
html2canvasでCanvasにイメージをコピーしておいて、<br />
ボタン押した時にjsPDFにaddImage()してみた。<br />
このときFabric.jsは使わなかった。
<script type="text/javascript" language="javascript" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="/js/jsPDF/jspdf.js"></script>
<script type="text/javascript" src="/js/jsPDF/jspdf.plugin.addimage.js"></script>
<script type="text/javascript" src="/js/jsPDF/libs/FileSaver.js/FileSaver.min.js"></script>
<script type="text/javascript" src="/js/fabric.min.js"></script>
<script type="text/javascript" src="/js/html2canvas.js"></script>
<div style="display:none;"><canvas id="c" width=1000 height=3000 ></canvas></div>
ここに非表示のcanvasタグ<br />
<img src="benzaiten_screenshot.jpg" id= "ss_img" style="display: none;"/>ここに非表示のimgタグ<br />
<script>
window.onload = function() {
  html2canvas(document.body,{
    onrendered: function(rendered_c){
      document.getElementById("ss_png_href").href = rendered_c.toDataURL("image/jpeg");
      var im=document.getElementById("ss_img")
      im.setAttribute('src', rendered_c.toDataURL("image/jpeg"));
      im.setAttribute('width', '500');

      //var destCtx = $('canvas').get(0).getContext('2d');
      var destCtx = document.getElementById('c').getContext('2d');
      destCtx.drawImage(rendered_c, 0, 0);
     }
  });
}
</script>

<script type="text/javascript" >
function getTextJpegBase64(text, fsize){
            var canvas = new fabric.Canvas('c',{backgroundColor : "#fff"});
            canvas.add(new fabric.Text(text, { fontFamily: 'Arial',fill: 'black',left: 0,top: 0,fontSize: fsize }));
            canvas.setHeight(fsize * 2);
            canvas.setWidth(790);
            canvas.calcOffset();
            canvas.renderAll();
            //return $('canvas').get(0).toDataURL('image/jpeg');
            return document.getElementById('c').toDataURL('image/jpeg');
}
$(document).ready(function() {
  $('#download-pdf').click(function(){
    var doc = new jsPDF();
    //doc.setFontSize(40);
    //doc.addImage(getTextJpegBase64("みつぎーくすげーわ。日本語表示", 24), 'JPEG',  10,  20);
    doc.addImage(document.getElementById('c').toDataURL('image/jpeg'), 'JPEG',  0, 0);
    doc.save('benzaiten_screenshot.pdf');
  });
});
</script>
</p><p>
<button id="download-pdf" >PDFをダウンロード</button>

こんなのをサーバーサイドでやるとなると

$ phantomjs rasterize.js http://somewhere somewhere.png
$ convert somewhere.png somewhere.pdf
実はたったこれだけw phantomjsとconvertを呼ぶだけでできるのさ。
PhantomJSの出力するイメージの幅が949xYなのでA4サイズで分割して複数ページのpdfに変換するには
$ phantomjs rasterize.js http://somewhere large.png
$ convert large.png -crop 949x1342 +repage paged-%02d.png 
$ convert paged-*.png paged.pdf


html2canvasは微妙に表示にバクがあったり、Feedjitのブログ・ウイジェットが表示されなかったりしてたけどPhantomJSはさすがに綺麗にでますな。

逆に複数ページのPDFファイルをページ毎のjpgファイルに変換するには
convert -flatten 2408.pdf image_%04d.png
透過した背景を白くするには
convert -flatten image_0000.png image_0000.jpg
だな。

投稿されたコメント:

コメント
コメントは無効になっています。