はじめに
この記事では、html2canvas と jsPDF を使ってWebページのデザインをそのままPDF化する方法を記載します。
以下の記事では、React-pdf を使ったPDF作成方法を記載していますが、React-pdf では独自のコンポーネントを利用して、PDFのUIを実装する必要があります。
一方、今回紹介する html2canvas と jsPDF を使えば、WebページのデザインをそのままPDF化できます。
各ライブラリの役割は以下の通りです。
-
html2canvas
: ブラウザ上のHTML要素を画像としてキャプチャできるライブラリ -
jsPDF
: 画像をPDFとして保存できるJavaScriptライブラリ
この2つを組み合わせることで、現在のWebページをそのままPDF化し、ユーザーにダウンロードさせることが簡単にできます。
開発環境
開発環境は以下の通りです。
- html2canvas 1.4.1
- jspdf 2.5.2
- Windows11
- React 18.3.1
- TypeScript 5.7.3
- Node.js 22.13.1
- npm 11.0.0
インストール
まずは html2canvas と jsPDF をインストールします。
npm install html2canvas jspdf
PDF化対象のWebページのデザイン実装
次にPDF化対象のWebページのデザインを実装します。
今回は useRef を渡した範囲のエリアをPDF化します。
import { useRef } from "react";
export function PdfExportSample() {
/** PDF化する対象の要素を参照するための useRef */
const contentRef = useRef<HTMLDivElement>(null);
return (
<div>
{/* PDFに変換する対象のエリア */}
<div ref={contentRef} style={{ padding: 24, backgroundColor: "blue" }}>
<h2>PDF化するコンテンツ</h2>
<p>この部分がPDFとして出力されます。</p>
</div>
{/* PDFダウンロードボタン */}
<button style={{ backgroundColor: "blue" }}>PDFをダウンロード</button>
</div>
);
}
PDF化処理の実装
最後に先ほど実装した箇所をPDF化する処理を実装します。
完成形は以下の通りです。処理順に解説していきます。
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
import { useRef } from "react";
export function PdfExportSample() {
/** PDF化する対象の要素を参照するための useRef */
const contentRef = useRef<HTMLDivElement>(null);
/** PDFダウンロード処理 */
const handleDownloadPdf = async () => {
if (!contentRef.current) return;
try {
// 1️⃣ 指定した要素をキャプチャしてCanvasに変換
const canvas = await html2canvas(contentRef.current);
// 2️⃣ Canvasを画像として取得(Base64のPNGデータ)
const imageData = canvas.toDataURL("image/png");
// 3️⃣ jsPDF インスタンスを作成(A4縦向き)
const pdf = new jsPDF({ orientation: "p", unit: "mm", format: "a4"});
// 4️⃣ PDFの幅を取得し、アスペクト比を維持した高さを計算
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
// 5️⃣ 画像をPDFに追加(左上から配置)
pdf.addImage({
imageData: imageData,
format: "PNG",
x: 0,
y: 0,
width: pdfWidth,
height: pdfHeight,
});
// 6️⃣ PDFをダウンロード
pdf.save("document.pdf");
} catch (error) {
console.error("PDF生成中にエラーが発生しました:", error);
}
};
return (
<div>
{/* PDFに変換する対象のエリア */}
<div ref={contentRef} style={{ padding: 24, backgroundColor: "blue" }}>
<h2>PDF化するコンテンツ</h2>
<p>この部分がPDFとして出力されます。</p>
</div>
{/* PDFダウンロードボタン */}
<button onClick={handleDownloadPdf} style={{ backgroundColor: "blue" }}>
PDFをダウンロード
</button>
</div>
);
}
1️⃣ 指定した要素をキャプチャしてCanvasに変換
const canvas = await html2canvas(contentRef.current);
html2canvas(contentRef.current)
を呼び出すことで、指定した要素(contentRef
)を Canvas(画像データ)に変換します。言い換えると、HTMLDivElement
を HTMLCanvasElement
に変換します。
この処理により、Webページのデザインをそのまま画像として取得 できます。
2️⃣ Canvasを画像として取得(Base64のPNGデータ)
const imgData = canvas.toDataURL("image/png");
canvas.toDataURL("image/png")
を使うことで、CanvasをPNG画像としてエンコード(Base64形式) できます。
imgData
には "data:image/png;base64,...."
のような文字列が入ります。
3️⃣ jsPDF インスタンスを作成(A4縦向き)
const pdf = new jsPDF({ orientation: "p", unit: "mm", format: "a4"});
new jsPDF({ orientation: "p", unit: "mm", format: "a4"})
で A4サイズのPDF(縦向き) を作成します。
-
"p"
: 縦向き("portrait"
のショートカット)- 横向きは
"l"
or"landscape"
- 横向きは
-
"mm"
: 単位をミリメートル に指定 -
"a4"
: A4サイズ(210mm × 297mm)
4️⃣ PDFの幅を取得し、アスペクト比を維持した高さを計算
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
画像をPDFの幅いっぱいに拡大し、アスペクト比を保持するために高さを計算します。
5️⃣ 画像をPDFに追加(左上から配置)
pdf.addImage({
imageData: imgData,
format: "PNG",
x: 0,
y: 0,
width: pdfWidth,
height: pdfHeight,
});
pdf.addImage({ imageData: imgData, format: "PNG", x: 0, y: 0, width: pdfWidth, height: pdfHeight})
で、左上 (0,0) に画像を追加します。
6️⃣ PDFをダウンロード
pdf.save("document.pdf");
pdf.save("document.pdf")
を呼び出すことで、PDFをダウンロード できます。"document.pdf"
はPDFファイル名になります。
動作確認
動作確認をします。「PDFをダウンロード」ボタンをクリックすると、実装時に指定した範囲のWebページがPDFファイルとして出力されます。
Webページを一度画像に変換してからPDF化しているため、PDFファイル内の文字検索等はできません。
まとめ
この記事では、html2canvas と jsPDF を使ってWebページのデザインをそのままPDF化する方法を記載しました。この方法を使えば、どんなWebページでも手軽にPDF化できます。
今後はページ分割方法やPDFファイルの容量が増えた時の対応法なども試していきたいです。