🐕
PDFMakeで日本語フォントを使用する
背景
JavaScriptでPDFを出力する場合、PDFMakeを使用する方法が一般的ですが、デフォルトのフォントがRobotoで日本語非対応になっています。vfs_fonts.jsという設定ファイルでフォントを変更することが出来ますが、フォントのバイナリをbase64で指定しなければならず、巨大なソースファイルが生まれてしまいます。
ビルド時、デバッグ時やSPAの初回ロード時に動作が著しく遅くなるため、解決策として行ったことをここに記します。
やること
バイナリをbase64で直打ちする方法をやめて、フォントファイルを別途ダウンロードさせることにします。PDFMakeを最初に使用するとき、フォントをダウンロード→base64化して変数にセットします。
PDFMakeを使用するまでフォントファイルは読み込まれないため、ビルド時、デバッグ時やSPAの初回ロード時の読み込みが遅くなりません。
具体的な方法
以下にReactのソースを示します。フォントファイルをダウンロード→base64化→pdfMakeにセットしています。pdfMakeのフォント設定は初回のみ行えばいいため、Reduxなどグローバル変数を管理するライブラリにpdfMakeのインスタンスを入れておいたほうがいいかもしれません。
サンプルプロジェクトは以下のGithubリポジトリにあります。
Vue.jsやAngularでもフォントファイルをダウンロード→base64化→pdfMakeにセットという方法は有効ですので試してみてください。
import logo from './logo.svg';
import './App.css';
import pdfMake from 'pdfmake';
import axiosBase from 'axios'
const axios = axiosBase.create({
baseURL: './',
headers: {
'Content-Type': 'application/x-font-ttf',
},
responseType: 'blob',
})
async function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = function() {
const result = this.result.split('base64,')[1]
resolve(result)
};
reader.readAsDataURL(blob)
})
}
async function onClick() {
if(pdfMake.vfs == null) {
const response = await axios.get('ipaexg.ttf')
if(response.status !== 200) {
return
}
const font = await blobToBase64(response.data)
pdfMake.vfs = {"ipaexg.ttf": font}
pdfMake.fonts = {
IPAEXGothic: {
normal: 'ipaexg.ttf',
},
};
}
const docDefinition = {
content: [`テスト出力`],
defaultStyle: {
font: 'IPAEXGothic',
},
};
pdfMake.createPdf(docDefinition).download();
}
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
PDFMake sample.
</p>
<p
className="App-link"
onClick={onClick}
>
Export PDF
</p>
</header>
</div>
);
}
export default App;
Discussion