コンテンツにスキップ

埋め込みライブプレビュー

埋め込みプレビューは、利用者の入力に追従する生きたプレビューです。左に自社のフォーム、 右に組み上がった文書。プレビューは訪問者のブラウザの中だけで、最終的な PDF を描くのと 同じレイアウトエンジンが動くので、見えているものがそのまま API の出力になります。

API キーは登場しません。iframe を認可するのは埋め込みトークンで、既定ではテンプレートを 表示することしかできません — 漏れても被害の範囲は画素で止まり、PDF のバイト列は自社の バックエンドが API キーでレンダリングします。書き出しを有効にして発行したトークンでは、 最終的なバイト列をブラウザの中で作ってホストのページへ渡すこともできます (ホストのページから PDF を作る)。

1. 埋め込みトークンを発行する

Section titled “1. 埋め込みトークンを発行する”

スタジオでキャンバスの API パネルを開き、埋め込みトークンを作ります。 iframe を置いてよいドメインを限定してください。この許可リストは Content-Security-Policy: frame-ancestors によってブラウザ側で強制されます。 手元の開発サーバーから iframe を表示したいときは、許可リストに localhost または 127.0.0.1 を書き足してください(ポートは不問、http / https のどちらでも)。 開発用にはトークンを分けることをおすすめします — localhost を許可したトークンでは、 自分の端末でサーバーを立てられる人なら誰でもプレビューを表示できます。 許可リストの変更が iframe 側の照合に反映されるまで最大1分かかります。すぐ試すときは ページをハードリロードしてください。

<iframe
id="composepdf-preview"
src="https://composepdf.com/embed/{token}"
style="border: 0; width: 100%; height: 640px"
></iframe>
<script>
const frame = document.getElementById('composepdf-preview');
// 自社フォームの入力ハンドラから呼びます。
function preview(data) {
frame.contentWindow.postMessage(
{ type: 'composepdf:data', v: 1, data },
'https://composepdf.com',
);
}
preview({ customer: { name: 'Acme Inc.' } });
</script>

composepdf:data のメッセージが届くたびに、新しいペイロードでプレビューが描き直されます。 その形は、レンダリング APIPOST する data オブジェクトとまったく同じです。

URL かメッセージで渡します。

  • ?outline=1 — データを参照している(変数の)部分を枠線で囲みます。フォームを配線している あいだに便利です。

  • postMessage({ type: 'composepdf:options', v: 1, outline: true }, …) — 同じものを実行中に切り替えられます。

  • ?bg=transparent — プレビュー自身の地色を抜き、ホストのページの地を透かします。 ?bg=%23ffffff で明示指定もできます(#rgb#rrggbb のみ。それ以外は既定に戻ります)。 紙そのものは、どちらの場合も枠と影を保ちます。

  • ?form=1 — 入力フォームを自社で配線する代わりに、テンプレートのデータ契約から iframe の中に生成します。「送信」は値を自社のページへ渡します(composepdf:submit)。 書き出しを許可したトークンでは、紙面の上の「PDF を書き出し」もそのまま出て、いま欄に ある値で閲覧者の端末に保存します。明細の配列はで編集します(1 列 = 1 つの欄、 1 行 = 1 件)。セルで Enter を押すと同じ列の次の行へ移り、最終行なら行が 1 つ 増えるので、10 行の明細もマウスに持ち替えずに打てます。

    各欄のラベルには、対応する変数の表示名(データ契約の description。API の スキーマやモバイルアプリに出るものと同じ文字列)が出ます。無ければ変数名そのままです。 表示名は studio の変数の面か、埋め込みパネルの欄の一覧で書けます。書いたあと テンプレートを公開すると、埋め込みに反映されます。

  • ?fields=customer(name,address),items(name,qty,price),total — 生成したフォームに 出す欄その順番。名前はデータ契約の欄で、表示したい順に並べます。その欄の 子は括弧で括って続けます — 明細の表のを並べ替えたり隠したりするのも この形です(埋め込みパネルではドラッグで並べ替えられます)。指定しなければ契約の 宣言順で全部出ます。括弧を書かなければ、その下は契約の順のままです。知らない名前は 無視され、ある階層で 1 つも一致しなければその階層は全部出ます — テンプレートを 公開し直しても、既に貼ってある iframe が空のフォームになることはありません。 括弧が閉じていない・名前が空、のように壊れた指定は全体が無視され、既定の フォームが出ます。?form=1 が要ります。

    隠した欄は空の値として payload に残ります。フォームが吐く形は API が期待する data そのままで、composepdf:data で入れた値も保たれます。ただし隠した欄の 検証エラーはフォームに出ません。必須の欄を隠す場合は、自社のページから composepdf:data で値を入れてください。

これらは埋め込みパネルの「見た目」で選べます(枠がどう見えるかのプレビューつき)。 選んでからトークンを発行すると、スニペットにその値が焼き込まれます。既に貼ってある iframe には、パネルに出るクエリをコピーして src の末尾に足してください。

  • ?accent=%230d437d — 書き出しボタンの色を変えます(#rgb#rrggbb のみ)。 渡すのは 1 色だけで、hover と押下時の濃淡はそこから導出され、文字色も明暗が 自動で切り替わるのでボタンは必ず読めます。それ以外の値は既定に戻ります。
  • ?actions=left|center|right|none — 紙面の上のボタンの置き場所。既定は centernone書き出しを禁じずにボタンだけ隠します — 自社のページ側から書き出しを 起こす場合(後述)に、PDF を作るボタンが 2 つ並ぶのを避けるためのものです。

プレビューは既定でコンテナ幅にフィットし、倍率の UI は出ません。狭い段では A4 が 読めない大きさになるので、変える口が 3 つあります。

  • ?zoom=1.5 — 初期倍率。フィット幅に対する倍数です。0.5〜3 に収められ、数値で ないものは幅フィットに戻ります。
  • ?zoomui=1 / + /「幅に合わせる」を紙面の上に出します。既定では出しません (iframe は自前のクロームを持たないためです)。この操作は書き出しボタンの 反対側に出ます — 通常は右端、?actions=right のときは左端。拡大縮小と書き出しが 1 つのツールバーに見えないようにするためです。枠が狭いときはそれぞれ自分の行に 落ち、同じ側を保ちます。
  • postMessage({ type: 'composepdf:options', v: 1, outline: false, zoom: 1.5 }, …) — 自社のツールバーから倍率を動かします。zoom: 'fit' で幅フィットへ戻り、zoom を 省略すれば倍率は変わりません。古い組み込みのメッセージはそのまま動きます。

倍率を上げると全ページを焼き直すので、長い文書では費用に注意してください。canvas は 1 辺 8192px で頭打ちにしてあり(それ以上は CSS で引き伸ばすので、ブラウザに描画を 放棄されることはありません)、それでも総量はページ数に比例します。

書き出しを有効にして発行したトークンでは、iframe が本物の PDF のバイト列を訪問者の CPU で 作れます — API と同じエンジン・同じ書体・同じバイト列です。ホストのページから頼み、受け取ります。

// composepdf:ready の後に。`data` を省くと、いま画面に映っている値で焼きます。
frame.contentWindow.postMessage(
{ type: 'composepdf:export', v: 1, data, download: false },
EMBED_ORIGIN,
);
window.addEventListener('message', (e) => {
if (e.origin !== EMBED_ORIGIN) return;
if (e.data?.type === 'composepdf:pdf') {
const blob = new Blob([e.data.pdf], { type: 'application/pdf' });
// …保存する・添付する・訪問者に渡す。
}
if (e.data?.type === 'composepdf:error') {
// 焼けなかった(必須項目が欠けている等)。
}
});

これでホスト主導の動線が組めます。自社の「発行する」ボタンが記録を書き、そのまま iframe に 焼かせる — 訪問者が二度押す必要はありません。data を渡すのが要点で、プレビューはデバウンスの ぶんだけ自社の state から遅れています。渡した値がそのまま焼かれ、契約検査もその値に当たります。

書き出しを有効にしていないトークンでは composepdf:export は何もしません。従来どおり API キーでサーバー側から焼いてください。

POST /v1/canvases/{canvasId}/pdf

この canvasIdGET /api/embed/{token}/doc が返すので、組み込み側の設定に持つのは 埋め込みトークン1つで済みます。

  • プレビューと書き出しは別の権限です。 既定の iframe は表示だけで、PDF のバイト列も ダウンロードのボタンもありません。上の動線を使うにはトークン側で書き出しを有効にします。
  • 下敷き PDF は描かれます。既存の様式に重ねる用途でも、焼く前に見た目を確かめられます。
  • プレビューは無料です。訪問者の CPU で描かれるので、レンダリングの利用量には数えません。 iframe からの書き出しも同じ理由で無料ですが、サーバー側に履歴が残りません — 控えが 要る業務では、受け取ったバイト列を自社のシステムに保存してください。