html2canvas を使って見ているページのスクリーンショット画像を生成してみた
公開日: today タグ:
JavaScript

背景

だんだんと秋も深くなり、周りではちらほら風邪をひく人も増えてきたそんな折。 ウェブページをPDFとしてダウンロードできるようにしてほしい、という要望をいただきました。

いやそれはブラウザから印刷しようとしてPDFとして保存すれば…とか、 必要な部分だけスクリーンショットを撮れば…など色々言ってはみましたが、 使う側のITリテラシーの問題もあり、PDFの生成からは逃れられませんでした。

過去に似たような要望をいただいたときは、 「サーバーサイドでブラウザを起動し、対象のウェブページを表示してPDFとして保存する」 というアプローチを取りました。 たとえば PhantomJS を使うとかですね。 今なら Google Chrome のヘッドレスモードが良いと思います。

で、以前やったときからしばらく経っていたので改めて調べてみると、 html2canvas という JavaScript ライブラリを見つけたので、 ちょっと使ってみて生まれたのがこの記事です。

タイトルを「スクリーンショット画像を生成してみた」としてますが、 厳密には「canvasにレンダリングしてみた」という形ですね。

html2canvas の原理

このライブラリは、指定したDOM以下の内容を canvas 要素にレンダリングしてくれます。 その後は canvas 側の機能(getImageDataなど)を使うことで画像データとして取得できたりします。

これは、通常ブラウザが行っているような HTML、CSS の解釈を JavaScript で独自に実装している、ということになります。 まだ対応していないスタイルがあったりすることもあり、また、 Chrome などのレンダリングエンジンと結果が一致するとも限らないので、 今ブラウザで見ている見た目そのままの画像が得られるかというとそうではない点に注意が必要です。

html2canvas をとりあえず使ってみる

ちゃんとやるなら npm install して…とかになると思いますが、 今回はとりあえず「作ってあるウェブページを html2canvas でレンダリングしたらどうなるか見たい」という点に絞って確認することにしました。

というわけでレンダリング結果の確認をしたいページを開き、 開発者コンソールに以下を打ち込んで html2canvas のスクリプトをロードします。

var script = document.createElement('script');
script.src = "https://html2canvas.hertzen.com/dist/html2canvas.min.js";
document.body.appendChild(script);

ここでスクリプトがロードされるまで少し待ちます。 で、以下のコードにより画面全体(このコードではhtmlタグ以下)を canvas にレンダリングして、 body の最後に追加します。

html2canvas(document.documentElement).then(canvas => {
    document.body.appendChild(canvas)
});

ということでコード実行後に画面をスクロールすると、 元の画面と大体似たようなものが現れると思います。

ただし、雑に body の最後へ追加しているだけなので、ページの作りによってはうまく2つ並ばなかったりします。

所感

自分の感想としては以下のような感じです。

  • ロゴ画像のサイズ指定が効いていないのか崩れたりする(原因未調査)ので、見た目を重視する場合は使いにくい
  • 何かしらの不具合を報告してもらうエラーレポート機能としては使えるかもしれない

自分がグラフィックライブラリでの描画になじみがないこともあり、 canvas にレンダリングする、というアプローチは面白いです。