PDFに文字を入れるのはWordやAcrobatのような有料ソフトじゃないとできないと思われがちです。私もこれまでAcrobatでノンブルを入れていました。
これまでペイントソフトにPDFを貼り付けて画像化していた人はぜひこのツールを試してくださると嬉しいです!PDFを画像化すると綺麗に文字が印刷されないので、PDFのままで作業してあげてください。
2日で作りました。勢いで作ったので一部作りが甘いかも(早速公開した後に小数点以下切り捨ての不具合修正をしました…)
仕様を絞ったこともあるのですが、自分の想像以上に簡単に実装できたので「もしかして既に誰かが作ってるんじゃないか?」と思い探しました。一応探した限りは見当たらなかったです。
PDF操作の要となっているのが「PDF-LIB」です。2019年頃に海外のかたが制作・公開された比較的新しいJSライブラリです。PDF-LIB以外にもPDFをブラウザ上で操作できるJSライブラリは存在していましたがどれも海外製なこともあり日本語フォント対応に一癖も二癖もあるようです。誰でもブラウザ上で簡単にPDFにノンブルを入れるシステムを作るというのは面倒で大変だという印象でこれまで作られていなかったんじゃないかと推測しています。
もちろん有料ソフトの方が使い方がわかりやすくてオプションも豊富です。InDesignだとかなり凝ったページデザインが作れて面白いです。
とはいえ、ノンブルを入れたいだけなのに有料ソフトを買うのは…と思う人も多いと思います。このツールを使って、この機にぜひアンソロや合同誌などの本や作品を作ってください!きっとこの世の誰かが救われます。
JavascriptでPDFを作成するライブラリまとめと比較
https://labelmake.jp/blog/javascript-pdf-generator-library
JSでの実装を考えたためJSのライブラリを探しました。そこでPDF-LIBの存在を知りました。
どうやら日本語フォントの扱いが比較的簡単らしいということで、PDF-LIBで色々検索しました。
Google Apps ScriptでPDFを操作する(PDF-LIB)
https://qiita.com/takatama/items/ac3284cae34a2d72ed53
最初にこちらの記事を拝読し、GASで実際に出力してPDF-LIBの処理をざっと確認。どこを変数にして動かすのか、コピペで実装させていただける手軽で簡単なプログラムで試しながら学びました。
GASはGoogleドライブのところから作れるので誰でも簡単にプログラミングができます。
htmlファイルのみでPDFを生成できるようなのでドラゴン桜計算プリントを作ってみた
https://qiita.com/nakazawaken1/items/e25d5de4aef736eddd61
JS内の情報を、HTMLを開いて出力する。まさにやりたいことだったので参考にさせていただきました。
Chrome拡張の Web Server for Chromeを利用されていたところから、「無理してレンタルサーバーにアップせず、ローカルサーバーで操作する形にすればいいんじゃないか?」と思い、色々な処理を書きました。
PDF-LIBでフォントをサブセット化
https://qiita.com/kaorumori/items/0b19f8a34f9892baa7c3
フォントのサブセット化をする処理を追加したところ、文字が一部出力されない現象を確認。こちらの記事を読んでみるとライブラリのバグのようでした。解決策も書かれていましたが、妥協することにしました。サブセット化しなくても印刷には問題無いので…。
PDF-LIB公式ドキュメント(英語)
PDFの読み込み部分や何やらは最終的に英語の公式ドキュメントを翻訳したり原文にしたり解読しながら実装。PDF-LIBはおそらくこの手のライブラリにしてはかなり公式ドキュメントが親切で充実している方かと思います。
ページ数が1桁数字の時は01、02…と表示されるようにする(pageNumが10未満の時に文字列として「0」を追加する)
タイトルだけ出力する(page.drawTextでノンブル+タイトルにしている部分をタイトルだけにする)
ページ数とタイトルの表示位置を個別に指定する(ノンブル+タイトルの出力処理をしている部分を分ける。タイトルの出力位置用の変数を追加する。など)
xは横軸、yは縦軸の指定になります。
x:0、y:0にするとページの左下に描画されます。左下が基点となります。
widthはPDFページの横幅、heightがPDFページの縦幅がプログラム上で自動で入力されます。
page.drawText(String(pageNum), {
x: numberX, // 横からの余白pt単位
y: height - fontSize - numberY, // 上からの余白pt単位
// y: numberY, // 下からの距離で計算させたい場合はこちらをご利用ください
size: fontSize,
font: font,
});
この部分が、PDFに文字を描画する処理になります。
page.drawText(String(pageNum), {
ここでページ番号String(pageNum)を記載しています。タイトルだけを出力したい時は以下のように変えます。
page.drawText(title, {
タイトルのみ出力したい時は、偶数ページのノンブルを出力するエリアを丸ごと削除するなど、他の処理も一緒に変えてください。
PDF-LIBは中央寄せや右寄せが実装されておらず、基本的には左から右へ向かって描画されるだけになります。その都合上偶数ページに実装するのは難しく、奇数ページだけにタイトルが載るような処理にしています。
JSでの実装なので上記以外にも何でもできます。実装が面倒なだけで色々できます。自分好みにカスタマイズしてお使いください。