質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.36%

  • JavaScript

    11189questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    4882questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • jQueryプラグイン

    319questions

    jQueryの拡張機能。 様々な種類があり、その数は膨大です。公開済みのプラグインの他にも、自作することもできます。 jQueryで利用できるようにしておくだけで、導入およびカスタマイズが比較的容易に行なえます。

【html2canvas】画面からはみ出た要素がキャプチャされない

解決済

回答 1

投稿 2017/12/04 14:03

  • 評価
  • クリップ 0
  • VIEW 328

nnahito

score 1409

 はじめに

急いでいます。

 やりたいこと

html2canvas.jsを使って、巨大なテーブル(画面からはみ出している)をキャプチャし、そのまま画像として表示させたい。

 やったこと

以下のようなJSを書きました。
(会社のデータを使っているので、全部を記載することが出来ません…申し訳ありません。)

// HTMLをイメージ化
let element = $('#all_seats')[0];
let elem_width = $('#all_seats').width();
html2canvas(element, {
    onrendered: function (canvas) {
        $('#all_seats_canvas').append(canvas);
        $('#all_seats').hide();
    },
    allowTaint: true,
    width: elem_width
});

画像は表示されましたが、画面からはみ出ている部分はキャプチャできませんでした。(透明画像になる)

 質問

はみ出た部分はキャプチャできないのでしょうか?
できるのであれば、方法をご教示いただけると幸いです。

出来なければ、代案をいただけると幸いです。

 参考サイト様

https://html2canvas.hertzen.com/documentation.html
http://bitwave.showcase-tv.com/html2canvas%E3%81%A7web%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%82%92%E5%8F%96%E3%82%8D%E3%81%863-%E3%80%90canvas/
http://techblog.kayac.com/html2canvas
https://st40.xyz/one-run/article/312/

 環境

html2canvas v0.5.0-beta4
Firefox Developer Edition 58.0b7 (64 ビット)
jQuery 3.2.1

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2017/12/04 14:39

    はみ出ないようにズームを変更して実行してみるとどうですか?

    キャンセル

  • nnahito

    2017/12/04 16:38

    ブラウザの縮小機能で縮小して実行したところ、確かに全体がイメージ化されました。しかし、データが多いのでセルが縦長になってしまいます…

    キャンセル

  • mts10806

    2017/12/04 16:40

    やはりはみ出た分はダメっぽいですね(確かかなり昔同じようなことがあって、無理やりはみ出ないようにおさめた記憶があります)

    キャンセル

回答 1

checkベストアンサー

+2

参考情報のみです. 以下試していません.


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の制限であり

.html2canvas-container { width: 3000px !important; height: 3000px !important; }


のようなコードを要するようです.


以下は代替案としてのHTML2canvasを用いない方法です.

HTMLツリーをSVGのforeignObject要素の配下とすることでHTMLグラフィックを画像として扱うことが可能になります. この画像をcanvas要素に転写すればよいのです. なお動作条件として以下があります.

  • 動作環境がFireFox/Chromeであること(Safari/Edgeでは動作しない)
  • スクリーンに表示されている内容とは異なる結果となる(異なるスタイルを指定できる)
  • Chromeでは余りに巨大なHTMLを描く際にクラッシュする可能性がある
    (かつてはSVGコードとして1MB程度の制限が有った)

以下実際のコードです.

<table id="drawtarget">
<caption>キャプション</caption>
<thead>
<tr><th>ヘッダー</th><th>ヘッダー</th><th>ヘッダー</th></tr>
</thead>
<tbody>
<tr><td>セル</td><td>セル</td><td>セル</td></tr>
<tr><td>セル</td><td>セル</td><td>セル</td></tr>
<tr><td>セル</td><td>セル</td><td>セル</td></tr>
<tr><td>セル</td><td>セル</td><td>セル</td></tr>
</tbody>
</table>
<img id="out"/>
//HTML構造をcanvas要素に描く
//(1)描画対象のノードを取得する
const table = document.querySelector("#drawtarget");
//(2)描画対象のouterHTMLで得られたHTMLコードをSVGのforeignObject要素配下となるように埋め込む
//SVGのサイズを変更することで出力サイズを調整できる
const svgsrc = `<svg xmlns="http://www.w3.org/2000/svg" width="500px" height="500px">
<style><![CDATA[
    /*ここにキャプチャ時のスタイルを指定する*/
    table{
        border-collapse: collapse;
    }
    table, th, td{
        border: 1px black solid;
    }
]]></style>
<foreignObject width="100%" height="100%">
<html xmlns="http://www.w3.org/1999/xhtml">
${table.outerHTML}
</html>
</foreignObject>
</svg>`;
//(3)得られたSVGのソースコードをdataURIスキーム形式のURL文字列に変換する
const url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgsrc);
//(4)上記URLをImageオブジェクトに設定し, 読み込まれたらcanvas要素に転写する
const image = new Image();
image.onload = e => {
    const canvas = document.createElement("canvas");
    canvas.width = image.naturalWidth;
    canvas.height = image.naturalHeight;
    const ctx = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0);
    out.src = canvas.toDataURL();//Safari/Edgeはここでエラーとなる
};
image.src = url;


この作業を行う過程で, SVGに埋め込んだHTML構造は元のHTML文書との関係が絶たれるため(style属性で埋め込まれたもの以外の)全てのスタイルが未設定となります. そのため, SVGコードの内部にstyle要素を用意しcanvas転写専用のスタイルを埋め込むことになります.
NOTE:動作原理(SVGをimg要素で読み込む動作)上,SVGは外部リソース(CSS, 背景画像, WEBフォント等)を参照することが出来ませんので, 必要に応じdataURIスキームに変換した上で全てをstyle要素に埋め込むようにします.

以下実行結果です
スクリプトの実行結果画像

投稿 2017/12/04 16:48

編集 2017/12/05 11:11

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/04 19:58

    ご回答ありがとうございます。

    実行してみましたが、ダメなようでした…

    キャンセル

  • 2017/12/04 20:08

    スタイルを無視して良い, もしくはブラウザの種類を固定してよいのであれば, HTML2canvasを用いずともWEB標準のSVGを介してHTMLの内容をcanvas要素に描くことが出来ます. もし必要であれば解説しますが?

    キャンセル

  • 2017/12/05 10:23

    ご返信ありがとうございます。

    > スタイルを無視して良い, もしくはブラウザの種類を固定してよい
    ブラウザはChromeメインで、サブがFirefoxです。
    スタイル無視は……どのくらい無視されるかがわかりませんが、一応お願いしてもよろしいでしょうか?

    キャンセル

  • 2017/12/07 18:31

    ありがとうございます!無事できました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.36%

関連した質問

同じタグがついた質問を見る

  • JavaScript

    11189questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    4882questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • jQueryプラグイン

    319questions

    jQueryの拡張機能。 様々な種類があり、その数は膨大です。公開済みのプラグインの他にも、自作することもできます。 jQueryで利用できるようにしておくだけで、導入およびカスタマイズが比較的容易に行なえます。