vue-pdfを使ってNuxt.jsでPDFスライドを表示させる

Published: 2021年2月19日 by tomsato

今回の記事について

Vue.js(Nuxt.js)でvue-pdfを使ってpdfスライドを表示させるサンプルを作成します

FranckFreiburger/vue-pdf

README.md通りに実装してもうまくいかないところがあったのでそのあたり含めてまとめます

他にもVue.jsでpdfを表示するライブラリを探してみたのですが良いのがなく、一番メジャーそう(?)なvue-pdfを動かせるように模索してみました

vue-pdfの使い方

Props

以下はvue-pdfコンポーネントのpropsに渡すことで実現できる機能

  • src: PDFのURLを指定してPDFを表示
  • page: PDFのページ番号を指定しての表示
  • rotate: 90度など回転させることができる

Events

以下はイベントとして検知できること例

  • @loaded: PDFがロードされた時に発生
  • @page-loaded(Number): ページがロードされた時に発生
  • @num-pages(Number): PDFのページ総数を取得
  • @error(Object): 予期せぬエラーがあった時に発生
  • @link-clicked(Number): リンクがクリックされた時

サンプルアプリケーションの作成

サンプルアプリケーションの完成品

画面内にスライドを表示させます

vue pdf 03

ボタン操作によってスライドの移動ができるようにして、スライド数と現在表示しているスライド番号も表示できるようにしています

サンプルのソースコードは以下にて公開しています

tomsato/sample-vue-pdf

今回のPDFスライドはPowerPoint Onlineで作成したスライドをPDFエクスポートしたものを表示しています

それ以外のPDFについては動作未確認ですご了承ください

Nuxt.jsの準備

Nuxt.jsのサンプルプロジェクトを作成

$ yarn create nuxt-app sample-vue-pdf
create-nuxt-app v3.5.2
✨  Generating Nuxt.js project in sample-vue-pdf
? Project name: sample-vue-pdf
? Programming language: TypeScript
? Package manager: Yarn
? UI framework: Bootstrap Vue
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: ESLint, Prettier, Lint staged files, StyleLint
? Testing framework: Jest
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? Continuous integration: None
? Version control system: Git

TypeScriptを使っているので使っていないプロダクトにこのサンプルを生かす場合は適宜読み替えてもらえればとmm

各種主要OSSバージョン

  • Nuxt.js:2.14.12
  • Vue.js:2.6.12

サンプルプロジェクトの起動

$ cd sample-vue-pdf
$ yarn dev

この状態で↓にアクセスするとページが見れる

http://localhost:3000/

vue pdf 01

この状態からPDFのスライドが見れるまで作り込んでいく

vue-pdfをREADME.md通りに追加・実装してみる

$ yarn add vue-pdf

入ったvue-pdfのバージョン:4.2.0

$ touch components/DisplayPdf.vue

DisplayPdf.vue の中身

<template>
  <div>
    <pdf src="/slide.pdf"></pdf>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
// @ts-ignore
import pdf from 'vue-pdf'

export default Vue.extend({
  components: {
    pdf,
  },
})
</script>

/slide.pdf でアクセスできるように、何でも良いのでpdfスライドを static/slide.pdf として配置する

pages/index.vue から上記コンポーネントを呼び出す

<template>
  <div class="container">
    <div>
      <h1 class="title">sample-vue-pdf</h1>
      <DisplayPdf />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
</script>

この状態でアクセスしてみると以下のエラーが出る

Unexpected token '<'

vue pdf 02

README.mdのサンプル通りに動かないので何かしらの対応が必要

Nuxt.js用に修正

issue: Working exemple with Nuxt #148

よりNuxt.jsだとサンプルが動かなさそう?🤔

上記issueを参考に実装し直してみる

以下のように修正してみる

差分についてはプルリクを見るとわかりやすいかもです

tomsato/sample-vue-pdf/pull/1

$ touch plugins/vue-pdf.js

plugins/vue-pdf.js を作成する

import Vue from 'vue'
import vuePdf from 'vue-pdf'

Vue.component('vue-pdf', vuePdf)

nuxt.config.js に以下の修正を入れる

plugins: [
  { src: '~/plugins/vue-pdf.js', mode: 'client' },
],

DisplayPdf.vue の修正

<template>
  <div>
    <client-only>
      <vue-pdf src="/slide.pdf" />
    </client-only>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
</script>

この状態でアクセスしてみる

vue pdf 03

アクセスできた

※ issueの英語が読めないので何故ダメだったか、何故この修正で動くかはわかっていないためわかる方はコメントいただけると嬉しいですmm

しかしこの状態だと1ページ目しか表示できていないのでもう少し改良を加える

ページ移動ボタンの実装、スライド数の表示対応

機能拡張を行う

  • 次のページへ進むボタン、前のページに戻るボタン
  • 現在のスライド数、スライド数を表示する

DisplayPdf.vue を修正する

<template>
  <div>
    <client-only>
      <button @click="prevPage">戻る</button>
      <button @click="nextPage">次へ</button>
       / 
      <vue-pdf
        :src="pdfUrl"
        :page="currentPageNum"
        @num-pages="totalPageNum = $event"
      />
    </client-only>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  data: () => ({
    pdfUrl: '/slide.pdf',
    currentPageNum: 1,
    totalPageNum: 0,
  }),
  methods: {
    prevPage() {
      if (this.currentPageNum <= 1) {
        return
      }
      this.currentPageNum = this.currentPageNum - 1
    },
    nextPage() {
      if (this.currentPageNum >= this.totalPageNum) {
        return
      }
      this.currentPageNum = this.currentPageNum + 1
    },
  },
})
</script>

表示するページ番号はvue-pdfのpage propsによって制御することができる合計スライド数もよしなに取得することができる、この辺りはREADME.mdを参考にする

prevPageやnextPageは表示スライド数をインクリメントデクリメントしていたり存在しないスライド番号を表示しないように制御させている

アクセスした時の画面、ボタンそ押すことでスライドを移動することができるようになる

日本語文字も文字化けせず表示できる

vue pdf 04

画像も表示することができる

vue pdf 05

図形も表示することができる

vue pdf 06

終わりに

最近はオンライン上でプレゼンをする機会が多く、Zoomなどのチャットでコメントをもらうように促しても盛り上がりにかけてしまうことが課題としてあるため、vue-pdfを使ってスライドを表示、Socket.IOを使ってリアルタイムにコメントやいいねなどを画面内に反映などできれば良いなと思いつつ今回はその第一歩としてvue-pdfを紹介しました、何かあればコメント頂けると嬉しいです

Vue

コメントを書く

※ 個別に返信が必要な時のみご記入ください

※ Emailは公開されません

※ 承認されると名前・コメントが下記に表示されます

コメント一覧

最近の投稿

ビジュアルリグレッションテストについてまとめ、ネットで調べると数多くのライブラリがありどれがどんな立ち位置なのか全体像がわかりずらかったのでどんな種類があるのか入門の入門としてまとめます、またPlaywrightを使って実際に触ってみました

社内ツールなどの超小規模なAPIをGolangで実装する際にフレームワークを使うべきかを、実際にnet/httpを使った実装とフレームワークを使った実装を比較することでどれだけ優位性があるかを見ていきたいと思います。今回はフレームワークにはシンプルで使いやすそうなEchoを使うことにします。

vue-pdfを使ってNuxt.jsで作成しているアプリケーションに pdfスライドを表示させるサンプルを作成しました README.md通りに実装してもうまくいかないところがあったのでそのあたり含めてまとめます

Vue.js / Nuxt.jsにおけるログインの実装方法をまとめる Auth0やNuxt.jsのAuth Moduleとmiddlewareについて調べつつサンプルを作成することで理解を深める

コンポーネント設計について考える Atomic DesignやPresentational Component, Container Componentについてまとめつつ 自分だったらVue.js / Nuxt.jsでどういうコンポーネント設計にするかについてまとめます

カテゴリ一覧

タグ一覧