はじめに
「ダッシュボードの画面をそのまま画像として保存したい」「SNSシェア用にコンポーネントを画像化したい」——こうした要望に応えるとき、多くの人がまず候補に挙げるのが html2canvas です。しかし html2canvas は開発が停滞気味で、CSSの新機能への対応に不安を感じることもあります。
そんなときに選択肢となるのが Html-To-Image です。DOM要素をCanvas経由で画像に変換するという発想は同じですが、より軽量な実装と活発なメンテナンスが魅力のライブラリです。この記事では、Html-To-Imageの特徴から実際の使い方までを解説します。
とはいえ、説明を読むより実際に動かした方が早いと思います。ボタンを押すとDOM要素がその場でPNG画像に変換されるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
Html-To-Imageとは
Html-To-Imageは、DOM要素をHTML5 CanvasとSVGを使ってPNG・JPEG・SVGなどの画像形式に変換できるJavaScriptライブラリです。人気の高かった dom-to-image をベースにフォークされ、TypeScriptでの型安全性やバグ修正、パフォーマンス改善が加えられています。
主な特徴
- 多彩な出力形式 - PNG、JPEG、SVG、Blob、Canvas、ピクセルデータまで、用途に応じて出力形式を選べます
- TypeScript対応 - 型定義が同梱されているため、TypeScriptプロジェクトでもそのまま安心して使えます
- 外部通信不要 - サーバーサイドのレンダリングを介さず、ブラウザ内だけで画像変換が完結します
- 軽量な依存構成 - 外部ライブラリへの依存が少なく、バンドルサイズを抑えやすい設計になっています
インストール
npm、yarn、pnpmのいずれでもインストールできます。
# npm
npm install html-to-image --save
# yarn
yarn add html-to-image
# pnpm
pnpm add html-to-image
CDN経由で直接読み込むことも可能です。
<script src="https://unpkg.com/html-to-image/dist/html-to-image.js"></script>
html-to-imageのサンプルを動かす
Html-To-Imageの中心となるのが toPng() 関数です。変換したいDOM要素を渡すだけで、その要素の見た目をそのままPNG画像のData URLとして返してくれます。以下は、カード要素をtoPng()でPNGに変換し、生成された<img>をその場に表示する要点部分です。
import { toPng } from "html-to-image";
const card = document.getElementById("card");
async function captureCard() {
const dataUrl = await toPng(card, { pixelRatio: 2 });
const img = document.createElement("img");
img.src = dataUrl;
document.getElementById("result").appendChild(img);
}
document.getElementById("btn").addEventListener("click", captureCard);
下のサンプルは実際に編集・実行できます。「PNGに変換」ボタンを押すと、上のグラデーションカードがtoPng()によって画像化され、結果がその下に表示されます。カード内のテキストやスタイルを書き換えてから再実行すると、変更がそのまま画像に反映されることが確認できます。
toPng()の第2引数に渡しているpixelRatio: 2を1に変えると、生成される画像の解像度が下がるのが分かります。カード内の<h2>や<p>のテキストを書き換えてから再度「PNGに変換」を押すと、DOM要素の見た目の変更がそのまま画像に反映されることも確認できます。
基本的な使い方
まずは、指定したDOM要素をPNG画像として取得する最もシンプルな例です。
import { toPng } from "html-to-image";
const node = document.getElementById("capture-target");
if (node) {
toPng(node)
.then((dataUrl) => {
const img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch((error) => {
console.error("画像の生成に失敗しました", error);
});
}
toPng 以外にも、用途に応じて次のような関数が用意されています。
import { toJpeg, toSvg, toBlob, toCanvas } from "html-to-image";
// JPEG形式で取得(品質は0〜1で指定)
const jpegDataUrl = await toJpeg(node, { quality: 0.95 });
// SVG形式で取得
const svgDataUrl = await toSvg(node);
// Blobとして取得(ファイルアップロードなどに便利)
const blob = await toBlob(node);
// Canvas要素として取得(さらに加工したい場合)
const canvas = await toCanvas(node);
実践的なユースケース
画面キャプチャをダウンロードさせる
管理画面のグラフやカード要素を、ボタン一つでPNGとしてダウンロードできるようにする実装です。
import { toPng } from "html-to-image";
async function downloadNodeAsImage(node: HTMLElement, fileName: string) {
const dataUrl = await toPng(node, {
cacheBust: true,
pixelRatio: 2, // Retinaディスプレイ向けに高解像度で書き出す
});
const link = document.createElement("a");
link.download = fileName;
link.href = dataUrl;
link.click();
}
const chartNode = document.getElementById("sales-chart");
if (chartNode) {
downloadNodeAsImage(chartNode, "sales-chart.png");
}
Reactコンポーネントを画像化する
Reactではrefでノードを取得し、任意のタイミングで画像化する実装がよく使われます。
import { useRef } from "react";
import { toPng } from "html-to-image";
function ShareCard() {
const cardRef = useRef<HTMLDivElement>(null);
const handleExport = async () => {
if (!cardRef.current) return;
const dataUrl = await toPng(cardRef.current);
const link = document.createElement("a");
link.download = "share-card.png";
link.href = dataUrl;
link.click();
};
return (
<div>
<div ref={cardRef} className="share-card">
<h2>今日の実績サマリー</h2>
<p>タスク完了数: 12件</p>
</div>
<button onClick={handleExport}>画像として保存</button>
</div>
);
}
quality や pixelRatio、backgroundColor といったオプションを組み合わせることで、印刷用のレポートやSNSシェア用のOGP画像生成など、幅広い用途に応用できます。
html-to-imageの出力形式を切り替える(toPng・toJpeg・toSvg・toBlob)
Html-To-ImageはtoPng()だけでなく、用途に応じてtoJpeg()・toSvg()・toBlob()を使い分けられます。写真的な画像はファイルサイズを抑えられるtoJpeg()、ベクター品質を保ちたいならtoSvg()、ファイルアップロードに渡すならBlobを直接返すtoBlob()が便利です。
import { toPng, toJpeg, toSvg, toBlob } from "html-to-image";
const node = document.getElementById("target");
const pngUrl = await toPng(node);
const jpegUrl = await toJpeg(node, { quality: 0.8 });
const svgUrl = await toSvg(node);
const blob = await toBlob(node); // アップロード用途などに
下のサンプルでは、同じカード要素に対して4つのボタンからtoPng・toJpeg・toSvg・toBlobをそれぞれ呼び出せます。toBlob()のみ戻り値がBlobオブジェクトなので、URL.createObjectURL()で表示用のURLに変換している点に注目してください。
4つのボタンを順に押し比べると、toSvg()はベクター形式のためカードを拡大しても輪郭がぼやけない一方、toJpeg()はqualityの値を下げるほどファイルサイズが小さくなる代わりに画質が粗くなる、といった違いが見えてきます。用途に応じてtoBlob()で取得したBlobをそのままFormDataに詰めてアップロードする、という使い方もよく行われます。
html-to-imageで特定の要素だけをキャプチャする
ページ全体ではなく、ネストした要素の一部だけを画像化したい場面もあります。Html-To-Imageは対象に指定したDOM要素の内側だけをレンダリングするため、親要素の枠線や周囲のUIを含めずにキャプチャできます。またbackgroundColorオプションを指定すると、透過部分を任意の色で塗りつぶせます。
import { toPng } from "html-to-image";
// 親要素ではなく、対象のカードだけをキャプチャする
const onlyThis = document.getElementById("only-this");
const dataUrl = await toPng(onlyThis, {
backgroundColor: "#ffffff",
});
下のサンプルでは、点線で囲まれた枠の中に「キャプチャ対象」カードがネストしていますが、toPng()に渡しているのはカード要素のidだけなので、周囲の枠や説明文は画像に含まれません。カラーピッカーでbackgroundColorを変更してから「この要素だけ変換」を押すと、背景色が反映された結果を確認できます。
カラーピッカーの値を変えるだけで、キャプチャ結果の背景色がその場で切り替わることが分かります。backgroundColorを指定しない場合は透過のままPNG化されるため、別の背景に重ねて使いたいアイコンやバッジの生成にも応用できます。
まとめ
Html-To-Imageは、DOM要素を手軽に画像へ変換できる軽量なライブラリです。TypeScriptとの相性がよく、PNG・JPEG・SVG・Blobなど出力形式の選択肢が豊富なため、スクリーンショット機能からシェア画像の生成まで幅広い場面で活用できます。
html2canvasからの乗り換えを検討している場合はもちろん、これから画面キャプチャ機能を実装する場合の第一候補としても、ぜひ試してみてください。
