html2canvasをスマートフォン(iPhone iOS Safari, Android Chromeのレスポンシブページ)に対応させる方法【JavaScript】

JavaScript

先日、『【PNG画像出力&エクセル出力対応】チーム分けWebツール・重複なしで均等に【グループ分けや組み分けを行うランダム生成オススメWebアプリ】』と『【簡易画像キャプチャ機能付き】テキストを比較して差分を表示するdiffツール【JavaScriptでWebツール】』というツールを作ったのですが、スマートフォンでhtml2canvasが動作せず、DOM要素の画像を生成することが出来なくてハマったので他の方のお役に立てればと思い記事にします。

html2canvasって何?

html2canvasは、ウェブページ上のHTML要素をキャプチャし、それを画像形式(主にPNG)に変換するJavaScriptライブラリです。このライブラリは、DOM(Document Object Model)を解析してレンダリングを行い、HTML要素をキャンバス要素に描画します。これにより、ウェブページのスクリーンショットをプログラム的に生成することが可能になります。

  1. クライアントサイドで動作:サーバー側の処理が不要で、ブラウザ上で直接動作します。
  2. カスタマイズ可能:スクリーンショットの生成にあたって、様々なオプションを指定できます。例えば、特定のHTML要素のみをキャプチャする、画像の解像度を指定するなどが可能です。
  3. クロスブラウザ互換性:多くのモダンブラウザで動作し、広い互換性を持っています。

ただ、完璧なレンダリングを保証するものではなく、CSSスタイルや複雑なレイアウトの一部は正確に描画されない場合があります。また、セキュリティ上の理由から、異なるオリジンの画像やリソースをキャプチャする際には制限があるので要注意です。

html2canvasをiOSのSafariに対応させる方法

日本語のソースが無く、少し手間取りましたが、結論を言うと「viewportの指定を一時的にpx指定してあげる」とうまくいきます。

以下のコードはhtml2canvasを利用して、DOM要素をPNGとしてダウンロードするコードです。

function downloadImage() {
    const viewportMeta = document.querySelector('meta[name="viewport"]');
    let originalViewportContent;

    if (viewportMeta) {
        originalViewportContent = viewportMeta.getAttribute('content');
        viewportMeta.setAttribute("content", "width=800"); // ここ大事1

        html2canvas(document.getElementById('tableContainer')).then(canvas => {
            viewportMeta.setAttribute("content", originalViewportContent); // ここ大事2

            const link = document.createElement('a');
            link.download = 'diff-capture.png';
            link.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
            document.body.appendChild(link); // DOMに追加
            link.click();
            document.body.removeChild(link); // メモリリーク対策でDOMから削除
        });
    }
}

html2canvasを実行する前にHTMLのViewportのcontentプロパティを保持しておきます(バックアップみたいなことです)。後で使うので、取っておいてください。
直後にsetAttributeでViewportのcontentを「width=800」にしていしてあげます。
800っていう数値はモバイル端末の画面サイズとかにすると良いかも。一瞬画面表示がキュゥゥってなったりするので、出来るだけ画面サイズに近くすることをおすすめします。

で、html2canvasを実行してあげます。するとDOMが画像として取得出来るようになるので、thenでViewportをバックアップした値(文字列)に戻してあげます。

その後はPCと同様の処理を進めるだけでOKです。

つまり、html2canvasを実行する直前にViewportのcontentプロパティをwidth=何らかの数値に変更してあげると正常にキャプチャが取れるようになるんですね。後はすぐ戻してあげれば良しです。

参考:https://stackoverflow.com/questions/59450855/html2canvas-works-on-desktop-but-not-on-mobile-how-to-fix

実行時にちょっと画面がおかしくなる(viewportが崩れる)のでPC画面のような表示になりますが、まあ、少しの間ですし、何か処理してるな感があるかなぁとポジティブにとらえています笑。
もし本気で一ミリも画面がおかしくなって欲しくない場合は、モーダルウィンドウなんかを挟んでローディングアイコンとか表示するのも面白いかもしれませんね。

Webブラウザで動くアプリ作るのって楽しいですね。制限や制約がネイティブアプリより解放されてる感じ(あくまで個人の意見)で作りやすいです。というかJSばっかり触ってるからかな。

みなさんもぜひHTML2CANVASを使って、業務の効率化を図ってみてください。非常に便利でお勧めです。

タイトルとURLをコピーしました