dom-to-imageを試す


HTML の Element を画像に変換するライブラリ dom-to-image を試しました。Chrome では良好ですが、Firefox では文字のサイズが変わってはみ出すようです。

See the Pen Test: dom-to-image by 七誌 (@7shi) on CodePen.

↑ 左が撮影元の Element、右がそれを画像化したものです。内容はデザインでよく使われる lorem ipsum と呼ばれるダミーテキストで、意味はありません。

シリーズの記事です。

  1. dom-to-imageを試す ← 今回の記事
  2. html2canvasを試す
  3. 複数の画像を生成してローカルに保存

dom-to-image

リポジトリ: tsayen/dom-to-image: Generates an image from a DOM node using HTML5 canvas

画像に変換する方法は README に説明があります。DeepL で翻訳したものに手を加えて引用します。

このライブラリは SVG の <foreignObject> タグの中に任意の HTML コンテンツを入れることができる機能を使っています。そして、その DOM ノードをレンダリングするためには、以下の手順を踏む必要があります。

  1. 元の DOM ノードを再帰的にクローン

  2. ノードと各サブノードのスタイルを計算して、対応するクローンにコピー

    • 疑似要素の再作成を忘れないでください。それらはどのような方法でもクローンされません。
  3. ウェブフォントを埋め込む

    • ウェブフォントを表す可能性のある @font-face 宣言をすべて探す
    • ファイルの URL を解析して、対応するファイルをダウンロード
    • base64 エンコードして、コンテンツを data: で表される URL としてインライン化
    • 処理されたすべての CSS ルールを連結して1つの <style> 要素にまとめ、それをクローンにアタッチ
  4. 画像を埋め込む

    • <img> 要素に画像 URL を埋め込む
    • CSS の background プロパティで使用される画像を、フォントと同様の方法でインライン化
  5. クローンされたノードを XML にシリアライズ

  6. XML を <foreignObject> タグにラップして SVG に入れて、データ URL を作成

  7. オプションで、PNG コンテンツや生のピクセルデータを Uint8Array として取得するには、SVG をソースとして Image 要素を作成して、オフスクリーンで Canvas を作成してレンダリングし、Canvas からコンテンツを読み込む。

  8. 完成!

以下の記事ではライブラリを用いずにこの方法を説明しています。

利用方法

自前でどこかに置かなくても、jsDelivr 経由で参照できます。

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/dom-to-image.min.js"></script>

README のサンプルコードを元に async/await で書き換えます。

(async () => {
  try {
    let img = new Image();
    img.src = await domtoimage.toPng(src);
    dst.appendChild(img);
  } catch (e) {
    console.error("oops, something went wrong!", e);
  }
})();

動作結果

この記事の冒頭に貼ったサンプルのスクリーンショットを見ます。

Chrome では下に少し余白ができますが、文字のサイズはそのままで画像化されます。

Firefox では文字のサイズが変わってしまうため、画像からはみ出してしまいます。

撮影対象がブラウザに依存するのでなければ、Chrome で利用するのが無難なようです。

Firefox

手動になってしまいますが、Firefox では対象の Element の右クリックで画像化できます。

  1. 右クリック → 要素を調査
  2. 開発ツールが表示される
  3. 選択されているノードを右クリック → ノードのスクリーンショットを撮影
  4. ダウンロードフォルダにスクリーンショットが生成

※ dom-to-image は自動化にメリットがあるとは思いますが…

なお、この方法は SVG の画像化にも利用できます。

参考

dom-to-image は以下の記事で知りました。