0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

jsPDF で PDF ファイルを作成

Posted at

やりたいこと

jsPDF で PDF ファイルを作成。

react プロジェクトの作成

npx create-react-app --template typescript test_pdf1

test_pdf1 のディレクトリ構成

.
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── download-pdf-button.tsx
│   ├── fonts
│   │   ├── NotoSansJP-Bold-base64.ts
│   │   ├── NotoSansJP-Bold.ttf
│   │   ├── NotoSansJP-Regular-base64.ts
│   │   ├── NotoSansJP-Regular.ttf
│   │   ├── create_NotoSansJP-Bold-base64.sh
│   │   └── create_NotoSansJP-Regular-base64.sh
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── pdf-creator.ts
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
└── tsconfig.json

jsPDF のインストール

npm install jspdf

日本語フォントの設定

Google Fonts で日本語対応フォントをダウンロード

Google Fonts で Noto Sans Japanese フォントをダウンロードする。

  • "Get font" をクリック
  • "Download all" をクリックして Noto_Sans_JP.zip をダウンロード
  • Noto_Sans_JP.zip を unzip
    • unzip Noto_Sans_JP.zip

日本語フォントを設定

  • src/fonts ディレクトリを作成
mkdir src/fonts
  • NotoSansJP-Regular.ttf を src/fonts にコピー
  • NotoSansJP-Bold.ttf を src/fonts にコピー
  • [Regular フォント] 以下のスクリプトを作成して実行し、NotoSansJP-Regular-base64.ts ファイルを作成
create_NotoSansRegularJP.sh
#!/bin/sh
TTF_FILE=NotoSansJP-Regular.ttf
TGT_FILE=NotoSansJP-Regular-base64.ts

echo '/* eslint-disable */' > ${TGT_FILE}
echo -n 'const NotoSansRegularJP = "' >> ${TGT_FILE}
base64 -w 0 ${TTF_FILE} >> ${TGT_FILE}
echo '"' >> ${TGT_FILE}
echo 'export default NotoSansRegularJP' >> ${TGT_FILE}
  • [Bold フォント] 以下のスクリプトを作成して実行し、NotoSansJP-Bold-base64.ts ファイルを作成
create_NotoSansBoldJP.sh
#!/bin/sh
TTF_FILE=NotoSansJP-Bold.ttf
TGT_FILE=NotoSansJP-Bold-base64.ts

echo '/* eslint-disable */' > ${TGT_FILE}
echo -n 'const NotoSansBoldJP = "' >> ${TGT_FILE}
base64 -w 0 ${TTF_FILE} >> ${TGT_FILE}
echo '"' >> ${TGT_FILE}
echo 'export default NotoSansBoldJP' >> ${TGT_FILE}

プログラム作成

メイン

src/App.tsx
import React from 'react';
import { DownloadPdfButton } from './download-pdf-button'

function App() {
  return (
    <div className="App">
      <DownloadPdfButton />
    </div>
  );
}

export default App;

PDF生成

src/pdf-creator.ts
import { jsPDF as JsPDF } from 'jspdf'
import NotoSansRegularJP from './fonts/NotoSansJP-Regular-base64'
import NotoSansBoldJP from './fonts/NotoSansJP-Bold-base64'

const FONT = 'NotoSansJP'
const fontFileRegular = './fonts/NotoSansJP-Regular.ttf'
const fontFileBold = './fonts/NotoSansJP-Bold.ttf'

const FONT_TYPES = {
  NORMAL: 'normal',
  BOLD: 'bold',
}

const FONT_SIZES = {
  NORMAL: 50,
  SMALL: 20,
}

export class PdfCreator {
  font: string
  doc: any

  constructor() {
    this.font = FONT
    this.doc = null
  }

  create = () => {
    const fileName = `output.pdf`
    this.doc = new JsPDF('l', 'mm', 'a4') // l: landscape

    // normal font
    this.doc.addFileToVFS(fontFileRegular, NotoSansRegularJP)
    this.doc.addFont(fontFileRegular, this.font, FONT_TYPES.NORMAL)

    // bold font
    this.doc.addFileToVFS(fontFileBold, NotoSansBoldJP)
    this.doc.addFont(fontFileBold, this.font, FONT_TYPES.BOLD)

    // create PDF
    this.doc.setFont(this.font, FONT_TYPES.NORMAL)
    this.doc.setFontSize(FONT_SIZES.NORMAL)

    const pageWidth = this.doc.internal.pageSize.getWidth()
    const pageHeight = this.doc.internal.pageSize.getWidth()
    const x = pageWidth / 2 - 100
    const y = pageHeight / 2 - 25

    this.doc.text('これは 1 ページ目です', x, y, { align: 'left' })
    this.doc.addPage() // 改ページ
    this.doc.text('これは 2 ページ目です', x, y, { align: 'left' })

    // page number
    this.addPageNumber()
    this.doc.save(fileName)
  }

  addPageNumber = () => {
    const totalPages = this.doc.internal.getNumberOfPages()
    const x = this.doc.internal.pageSize.width - 20
    const y = this.doc.internal.pageSize.height - 10

    for (let i = 1; i <= totalPages; i++) {
      const pageNumberText = `${i} / ${totalPages}`
      this.doc.setPage(i)
      this.doc.setFont(this.font, FONT_TYPES.NORMAL)
      this.doc.setFontSize(FONT_SIZES.SMALL)
      this.doc.text(pageNumberText, x, y, { align: 'right' })
    }
  }
}

ダウンロードボタン

src/download-pdf-button.tsx
import { PdfCreator } from './pdf-creator'

export const DownloadPdfButton = () => {
  const download = () => {
    const pdfCreator = new PdfCreator()
    pdfCreator.create()
  }

  return (
    <button onClick={download}>Download PDF</button>
  )
}

サーバ起動

npm run start

PDF ダウンロード

http://{アドレス}:3000/ にアクセスし、"Download PDF" ボタンをクリックすると、PDF ファイルをダウンロードできる。

PDF ファイル

pdf.png

参考

jsPDFで日本語が文字化けする問題を解消する方法

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?