PerfectVector
著者: Irene Kim2 分で読める

jsPDFとSVG:ブラウザーで作るPDFにロゴのパスを残す

svg2pdf.jsとjsPDFでSVGロゴを配置し、対応するパスを保持します。PDF上のサイズを設定し、同じ画像のラスター出力と保存したファイルを比較します。

目次

jsPDFでブラウザー生成のPDFにSVGロゴのパスを入れるには、svg2pdf.jsを読み込み、SVG要素をawait doc.svg(...)へ渡してから文書を保存します。ラスター画像でよい場合だけaddSvgAsImageを選びます。入力がSVGでも、結果のPDFにSVGのパスが含まれるとは限りません。

svg2pdf.jsの使用例は、要素を使った非同期呼び出しを説明しています。jsPDFのSVGモジュール実装は、もう一方の方法を示しています。キャンバスへ描画し、JPEGにエンコードして、その画像をPDFに追加します。

請求書、チケット、レポートのロゴでは、元SVGを編集可能なマスターとして保持します。このガイドでは単純な2色のエンブレムをテストし、PDFのポイント単位で配置を設定して、保存したオブジェクトを確認します。SVGのすべての機能が変換後に残るとは想定しません。

必要な出力を選ぶ

方法渡すもの確認するもの
await doc.svg(element, options)svg2pdf.jsを読み込んだ状態でSVGのDOM要素対応する形状、塗り、穴、配置、埋め込み画像
await doc.addSvgAsImage(text, x, y, width, height)文字列のSVGマークアップ配置に加え、ラスター解像度と背景
元のデザインアプリからPDFを書き出す編集可能なデザインファイル書き出し設定と最終PDFのオブジェクト

3つ目は、JavaScriptで組み立てる文書ではなく、準備済みのロゴPDFが必要な場合に役立ちます。ブラウザー外の文書処理には、LaTeXでSVGを使うガイドが、別の書き出しと取り込みの工程を説明しています。Nodeの文書処理には、PDFKitのSVG例が、SVG文書全体の挿入と1本のパスの解析を区別しています。

納品物がスライド資料なら、PptxGenJSのSVG画像ガイドを使ってください。別の文書形式にPDFの設定を適用するのではなく、ロゴの縦横比、書き出したPPTXのメディア、プレゼンテーションアプリでの見た目を確認します。

まずバージョンを固定した小さな例を実行する

この例は、ブラウザーでjsPDF 4.2.1とsvg2pdf.js 2.8.1を使って実行しました。テストしたバージョンであり、将来のリリースの保証ではありません。パッケージ名は接尾辞を含めてsvg2pdf.jsです。似た名前のパッケージは異なる手順に使われる場合があります。

JavaScriptバンドラーを使う小さなブラウザープロジェクトに、次をインストールします。

npm install jspdf@4.2.1 svg2pdf.js@2.8.1

この独自エンブレムを入力に使います。リングには偶奇規則による実際の開口部があります。2本目のパスは丸みのある頂点です。フォント、リンクしたファイル、フィルター、埋め込みラスター画像はありません。

import { jsPDF } from 'jspdf';
import 'svg2pdf.js';
 
const svgText = `<svg xmlns="http://www.w3.org/2000/svg"
  width="240" height="160" viewBox="0 0 240 160">
  <path fill="#174d64" fill-rule="evenodd"
    d="M20 80 C20 15 120 15 120 80 C120 145 20 145 20 80 Z
       M48 80 C48 111 92 111 92 80 C92 49 48 49 48 80 Z"/>
  <path fill="#e66d45"
    d="M130 120 L170 35 Q178 20 188 35 L225 120 Z"/>
</svg>`;
 
async function makeVectorPdf() {
  const svg = new DOMParser()
    .parseFromString(svgText, 'image/svg+xml')
    .documentElement;
  const doc = new jsPDF({
    unit: 'pt',
    format: [300, 220],
    orientation: 'landscape'
  });
  await doc.svg(svg, { x: 30, y: 30, width: 240, height: 160 });
  return doc;
}
 
const doc = await makeVectorPdf();
doc.save('logo-vector.pdf');

Node.jsのスクリプトで直接実行せず、ブラウザーで実行します。ライブラリの使用法と対象範囲の説明では、動作するブラウザーDOMを必要とし、SVG対応の制限を示しています。サーバーレンダリングのアプリでは、クライアント側の書き出しハンドラーにこの処理を置きます。

ここでの文字列は、信頼できる固定画像です。アプリが任意のSVGアップロードを受け付ける場合、XMLの解析だけではサニタイズになりません。アップロード機能を作る前に、ユーザー提供SVGのサニタイズと実行の隔離について、ライブラリの指針に従ってください。

viewBoxとは別に配置を設定する

この例ではunit: 'pt'により、PDFの測定単位がポイントになります。ページは300 × 220ポイントで、画像のビューポートは左と上から30ポイントの位置に始まり、240 × 160ポイントを占めます。jsPDFのコンストラクタードキュメントは、文書の単位、形式、向きのオプションを説明しています。

SVGのviewBox="0 0 240 160"は内部座標を表し、PDFのページサイズではありません。配置先の幅と高さを同じ3:2の比率に保つと、意図した収まりを確認しやすくなります。配置画像を半分にするにはwidth: 120, height: 80を使います。元のパス座標は変更不要です。

PDFでの位置を調べる前に、書き出すSVGに明示的な寸法と適切なviewBoxを設定します。予想外に大きい空白の縁は、SVGのキャンバスに由来する場合があります。xとyを動かすと、その空白も含めたSVGビューポート全体が移動します。

保存した2つのPDFを確認する

比較用に、同じブラウザーで意図的にラスター化した次の版も作りました。

const raster = new jsPDF({
  unit: 'pt',
  format: [300, 220],
  orientation: 'landscape'
});
await raster.addSvgAsImage(svgText, 30, 30, 240, 160);
raster.save('logo-raster.pdf');

この方法では、jsPDFにインストールされたcanvg依存パッケージ3.0.11を使いました。両方のPDFを保存して開き直し、同じ倍率で描画しました。PyMuPDFによる描画と画像の検査では、次の結果でした。

保存ファイル報告された描画パス報告された埋め込み画像
logo-vector.pdf塗りのあるパス2本0
logo-raster.pdf0JPEG 1枚、240 × 160ピクセル

ベクターファイルのコンテンツストリームには、曲線コマンドとリングの偶奇規則の塗りが含まれました。ラスターファイルには画像オブジェクトが配置されました。この数は小さな今回の素材についての結果です。複雑なSVGでは別のオブジェクトが生成されたり、元からラスター内容を含んだりする場合があります。

リングと丸い頂点のPDFを同じ倍率で表示した比較。左は2本のベクターパス、右は1枚のJPEG画像です
同じ独自エンブレムをブラウザーから2つの方法で書き出した結果です。保存PDFの検査では、doc.svgに塗りのあるパス2本、addSvgAsImageに240 × 160ピクセルのJPEG 1枚がありました。ラスターの方法では、このテストに示す黒い背景も生じました。

黒い矩形は、このラスター書き出しで観察した結果です。以前透明だったリングの穴も含みます。JPEGはアルファ透明度を保持しないため、この方法でSVGの透明部分が残ると想定しないでください。特に色付きの文書パネルへロゴを載せる場合は、実際に必要な背景を確認します。

拡大するだけでは十分な根拠になりません。どのPDFビューアーも、最終的には画面へピクセルを描きます。PDFのオブジェクトを調べ、保存した見た目をSVGマスターと比較します。Popplerのpdfimages -list logo-raster.pdfなどのコマンドで、埋め込み画像を一覧にできます。画像一覧が空でも、意図した形状が正しく書き出された証明にはなりません。ページ自体が空かもしれないので、描画内容と見た目も確認してください。

書き出しで失敗している部分を直す

症状役立つ最初の確認
doc.svgがない書き出し呼び出し前にsvg2pdf.jsのインポートが実行されるか確認します
画像が現れる前にファイルが保存される保存前にSVG変換をawaitします
ロゴがずれる、または予想より小さいPDFの単位、配置先寸法、元のviewBoxを比較します
一部の細部が消えるコピーを問題のSVG機能だけに減らし、対応する手順と比較します
ベクターのはずのロゴにピクセルがある元SVGとPDFの画像オブジェクトを調べます

SVG自体がビットマップを包んでいる場合があります。ベクター対応の書き出しツールへ渡しても、ピクセルは編集可能な輪郭へトレースされません。PDF設定を変える前に、埋め込みラスターの検査ガイドを使います。

このテストは、テキストレイアウト、フィルター、外部画像、任意のCSSを対象にしていません。svg2pdf.jsは、SVGの一部に対応することを明示しています。文字には変換前にフォント設定の指示に従うか、その判断が適切ならデザイン元でアウトラインを準備します。将来文字を変える必要があるなら、文字を編集できるマスターを保持してください。

PerfectVectorでロゴの元データを準備する

きれいなベクターのロゴがすでにある場合は、その元データを使います。PNGやJPGしか残っていない場合は、PerfectVectorでPDF作成前に編集可能な形状を復元できます。ロゴをベクター化し、SVGエディターで外側の輪郭、小さな開口部、別々の色を確認します。ロゴの準備ガイドでは、この確認を詳しく説明しています。

PerfectVectorは、この手順用にラスター画像を準備します。jsPDFへSVG対応を追加したり、書き出しツールの非対応機能を修復したりはしません。復元したパスを元画像と比較し、必要な細部を簡略化または描き直してから、PDFの確認をやり直します。トレースで必要な細部が失われる写真は、画像として保持してください。画像のベクター化ガイドは、その元データの選択を説明しています。

よくある質問

addSvgAsImageはSVGをベクターパスとして保持しますか? いいえ。テストしたjsPDF 4.2.1の実装は、キャンバス経由でSVGを描画し、JPEGを埋め込みます。対応する形状をPDFの描画内容へ変換するには、svg2pdf.jsとdoc.svgを使います。

doc.svgはSVGのファイル名を受け取りますか? ここで示したAPIはSVGのDOM要素を受け取ります。信頼できるファイルを先に読み込んで解析するか、既存のSVG要素を選び、その要素をdoc.svgへ渡して結果をawaitします。

どのSVGもPDFで同じ見た目になりますか? いいえ。svg2pdf.jsはSVGの限られた部分に対応しています。フォント、画像、効果、寸法、背景を含む実際の画像をテストし、使用前に保存したPDFを開き直してください。

参考資料

  1. yWorks — svg2pdf.jsの使用法と対象範囲 — SVG要素のAPI、非同期変換、フォント設定、ブラウザー要件、対応範囲の制限。
  2. jsPDF — バージョン4.2.1のSVGモジュール — addSvgAsImageが使うキャンバスとJPEGの実装。
  3. jsPDF — コンストラクターリファレンス — PDF文書の単位、ページ形式、向きのオプション。
  4. PyMuPDF — ページの検査 — 保存したテストファイルの確認に使った描画と画像の検査方法。

ラスターのロゴしかない場合は、ロゴから編集可能なSVGを準備し、輪郭と開口部を確認してから、選んだPDFの方法で書き出し、保存したオブジェクトと背景を調べてください。

ブログのその他の記事

編集しやすい
よりきれいなSVGから始めましょう