参考情報のみです. 以下試していません.
HTML2Canvas does not render full div, only what is visible on screen?
https://stackoverflow.com/questions/36213275/html2canvas-does-not-render-full-div-only-what-is-visible-on-screen
によればこの動作はHTML2canvasの制限であり
CSS
1.html2canvas-container { width: 3000px !important; height: 3000px !important; }
のようなコードを要するようです.
以下は代替案としてのHTML2canvasを用いない方法です.
HTMLツリーをSVGのforeignObject
要素の配下とすることでHTMLグラフィックを画像として扱うことが可能になります. この画像をcanvas
要素に転写すればよいのです. なお動作条件として以下があります.
- 動作環境がFireFox/Chromeであること(Safari/Edgeでは動作しない)
- スクリーンに表示されている内容とは異なる結果となる(異なるスタイルを指定できる)
- Chromeでは余りに巨大なHTMLを描く際にクラッシュする可能性がある
(かつてはSVGコードとして1MB程度の制限が有った)
以下実際のコードです.
HTML
1<table id="drawtarget">
2<caption>キャプション</caption>
3<thead>
4<tr><th>ヘッダー</th><th>ヘッダー</th><th>ヘッダー</th></tr>
5</thead>
6<tbody>
7<tr><td>セル</td><td>セル</td><td>セル</td></tr>
8<tr><td>セル</td><td>セル</td><td>セル</td></tr>
9<tr><td>セル</td><td>セル</td><td>セル</td></tr>
10<tr><td>セル</td><td>セル</td><td>セル</td></tr>
11</tbody>
12</table>
13<img id="out"/>
JavaScript
1//HTML構造をcanvas要素に描く
2//(1)描画対象のノードを取得する
3const table = document.querySelector("#drawtarget");
4//(2)描画対象のouterHTMLで得られたHTMLコードをSVGのforeignObject要素配下となるように埋め込む
5//SVGのサイズを変更することで出力サイズを調整できる
6const svgsrc = `<svg xmlns="http://www.w3.org/2000/svg" width="500px" height="500px">
7<style><![CDATA[
8 /*ここにキャプチャ時のスタイルを指定する*/
9 table{
10 border-collapse: collapse;
11 }
12 table, th, td{
13 border: 1px black solid;
14 }
15]]></style>
16<foreignObject width="100%" height="100%">
17<html xmlns="http://www.w3.org/1999/xhtml">
18${table.outerHTML}
19</html>
20</foreignObject>
21</svg>`;
22//(3)得られたSVGのソースコードをdataURIスキーム形式のURL文字列に変換する
23const url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgsrc);
24//(4)上記URLをImageオブジェクトに設定し, 読み込まれたらcanvas要素に転写する
25const image = new Image();
26image.onload = e => {
27 const canvas = document.createElement("canvas");
28 canvas.width = image.naturalWidth;
29 canvas.height = image.naturalHeight;
30 const ctx = canvas.getContext("2d");
31 ctx.drawImage(image, 0, 0);
32 out.src = canvas.toDataURL();//Safari/Edgeはここでエラーとなる
33};
34image.src = url;
この作業を行う過程で, SVGに埋め込んだHTML構造は元のHTML文書との関係が絶たれるため(style
属性で埋め込まれたもの以外の)全てのスタイルが未設定となります. そのため, SVGコードの内部にstyle
要素を用意しcanvas転写専用のスタイルを埋め込むことになります.
NOTE:動作原理(SVGをimg要素で読み込む動作)上,SVGは外部リソース(CSS, 背景画像, WEBフォント等)を参照することが出来ませんので, 必要に応じdataURIスキームに変換した上で全てをstyle
要素に埋め込むようにします.
以下実行結果です