Vue は PDF.js を統合して PDF プレビューを実装し、透かしを追加する手順を実行します。

Vue は PDF.js を統合して PDF プレビューを実装し、透かしを追加する手順を実行します。

成果を達成する

利用可能なプラグインの紹介

Mozilla は PDF.js と pdfjs-dist を提供しています。両者の違いは次のとおりです。

  • 完全な PDF ビューアである PDF.js は、提供される viewer.html を直接使用して、完全なスタイルと関連機能を含む PDF コンテンツを表示できます。利点は、迅速な統合が可能で、ビューアの機能やスタイルを自分で実装する必要がないことです。デメリットとしては、スタイルや機能をカスタマイズしたい場合に面倒になってしまうことです。
  • PDF.js のビルド済みバージョンである pdfjs-dist には、PDF コンテンツのレンダリング機能のみが含まれています。ビューアのスタイルや関連機能は自分で実装する必要があります。

公式 Vue プラグイン ライブラリである Awesome Vue.js が推奨する vue-pdf は、pdfjs-dist をカプセル化したものです。一般的に、vue-pdf を使用すると、PDF プレビュー効果をすばやく実現できます。

ニーズに応じてプラグインを選択する

私たちの要件は、既存のページに PDF プレビューを実装しながら、PDF コンテンツに透かしを追加することです。

PDF.js のフルバージョンは肥大化しすぎています。vue-pdf はプレビュー効果を素早く実現できますが、透かしを追加するときに PDF を表示するキャンバスを 2 回レンダリングする必要があります。試してみたところ、Failed to execute 'drawImage' on 'CanvasRenderingContext2D': Overload resolution failed. というエラーがスローされることがわかりました。

結局、pdfjs-distを直接統合してすべての機能を完成させることにしました。

プラグインのインストールとインポート

インストール

yarn pdfjs-dist を追加する

導入

workerSrc は手動で指定する必要があります。そうしないと、偽のワーカーの設定に失敗しましたというエラーがスローされます。

ファイルはローカルディレクトリ node_modules/pdfjs-dist/build/pdf.worker.js に存在しますが、実際にインポートするとエラーが報告されるため、CDN アドレスの下にある pdf.worker.js のみを使用できます。 PDFJS.version を渡すことで、インポートの柔軟性を高めることができます。

'pdfjs-dist' から * を PDFJS としてインポートします。

PDFJS.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDFJS.version}/pdf.worker.js`

プラグインを初期化する

コンテンツをレンダリングするためのキャンバスノード

<canvas id="pdfCanvas"></canvas>

PDFJSインスタンスを受信するために使用されるオブジェクト

小道具: {
 // PDF ファイルの実際のリンク URL: {
 タイプ: 文字列
 }
},
データ () {
 戻る {
 合計ページ: 1,
 // PDFJS インスタンス pdfDoc: null
 }
},
メソッド: {
 _initPdf() {
 PDFJS.getDocument(this.url).promise.then(pdf => {
 // ドキュメントオブジェクト this.pdfDoc = pdf
 //ページ総数 this.totalPage = pdf.numPages
 // ページをレンダリングします this.$nextTick(() => {
 this._renderPage()
 })
 })
 }
}

リンクの変更を監視し、インスタンスを初期化する

外部からのURLが有効な場合、PDFビューアの初期化機能が起動されます。

時計:
 'url' (値) {
 もし(!val) {
 戻る
 }

 this._initPdf()
 }
},

PDFコンテンツのレンダリング

現在のページ比率を取得して、コンテンツの実際の幅と高さを計算します

メソッド: {
 _getRatio(ctx) {
 dpr = window.devicePixelRatio || 1 とします
 bsr = とします
 ctx.webkitBackingStoreピクセル比 ||
 ctx.mozBackingStoreピクセル比 ||
 ctx.msBackingStoreピクセル比 ||
 ctx.oBackingStoreピクセル比 ||
 ctx.backingStoreピクセル比 ||
 1

 dpr / bsrを返す
 }
}

現在のページをレンダリングする

page.getViewport({ scale }) のスケールは非常に重要で、レンダリングされたコンテンツが親コンテナ全体を埋めることができるかどうかに直接関係します。したがって、ここでは親コンテナの幅とページ自体の幅がそれぞれ取得されます。親コンテナの幅/ページ幅の比率は、実際のページをどれだけ拡大する必要があるかの比率です。

page.view は、x 軸オフセット、y 軸オフセット、幅、高さの 4 つの値を持つ配列です。 実際の幅を取得するには、現在のページ比率も考慮する必要があるため、page.view[2] * ratio を使用して実際の幅を計算します。

データ () {
 戻る {
 現在のページ: 1,
 合計ページ: 1,
 幅: 0,
 高さ: 0,
 pdfDoc: ヌル
 }
},
メソッド: {
 _renderPage() {
 this.pdfDoc.getPage(this.currentPage).then(ページ => {
 キャンバスを document.querySelector('#pdfCanvas') にします。
 ctx = canvas.getContext('2d') とします。
 // ページ比率を取得する let ratio = this._getRatio(ctx)

 // ページ幅とビューポート幅の比率がコンテンツ領域の拡大率です。let dialogWidth = this.$refs['pdfDialog'].$el.querySelector('.el-dialog').clientWidth - 40
 pageWidth = page.view[2] * 比率とする
 scale = dialogWidth / pageWidth とします。

 viewport = page.getViewport({ scale }) とします。

 // コンテンツ領域の幅と高さを記録します。これは後で透かしを追加するときに必要になります。this.width = viewport.width * ratio
 this.height = viewport.height * 比率

 キャンバスの幅 = this.width
 キャンバスの高さ = this.height

 // スケーリング比率 ctx.setTransform(ratio, 0, 0, ratio, 0, 0)

 ページ.レンダリング({
 キャンバスコンテキスト: ctx,
 ビューポート
 }).promise.then(() => {})
 })
 }
}

ページジャンプの実装

レンダリング順序の混乱を防ぐためにレンダリングキューを準備する

ページジャンプがトリガーされると、レンダリングを開始するかどうかは現在レンダリング中のページがないかどうかによって決まるため、_renderPage() 関数を直接呼び出すのではなく、_renderQueue() 関数が呼び出されます。

データ () {
 戻る {
 // キューレンダリング中かどうか: false
 }
},
メソッド: {
 _renderQueue() {
 if (this.rendering) {
 戻る
 }

 this._renderPage()
 }
}

ページをレンダリングするときにキューの状態を変更する

メソッド: {
 _renderPage() {
 // キューが開始されます this.rendering = true

 this.pdfDoc.getPage(this.currentPage).then(ページ => {
 // ... 実装コードを省略 page.render({
 キャンバスコンテキスト: ctx,
 ビューポート
 }).promise.then(() => {
 // キューが終了します this.rendering = false
 })
 })
 }
}

ページめくり機能の実装

データ () {
 戻る {
 現在のページ: 1,
 合計ページ: 1
 }
},
計算: {
 // ホームページですか firstPage() {
 this.currentPage <= 1 を返す
 },
 // 最後のページかどうか lastPage() {
 this.currentPage >= this.totalPage を返します。
 },
},
メソッド: {
 // ホームページにジャンプ firstPageHandler () {
 if (this.firstPage) {
 戻る
 }

 this.currentPage = 1
 this._renderQueue()
 },
 // 最後のページにジャンプ lastPageHandler () {
 最後のページの場合
 戻る
 }

 this.currentPage = this.totalPage
 this._renderQueue()
 },
 // 前のページ previousPage() {
 if (this.firstPage) {
 戻る
 }

 this.currentPage--
 this._renderQueue()
 },
 // 次のページ nextPage() {
 最後のページの場合
 戻る
 }

 this.currentPage++
 this._renderQueue()
 }
}

ページコンテンツにタイルテキストの透かしを追加する

フロントエンドに透かしを追加する方法は、描画にキャンバスを使用することであることに間違いはありません。

最初の解決策は、コンテンツ領域の上層をブロックする透明なマスク レイヤーとして div を用意し、canvas.toDataURL('image/png') を使用して、canvas で描画された透かしを Base64 形式でエクスポートし、マスク レイヤーの背景画像としてタイル化することでした。 効果は得られますが、この方法ではブラウザコンソールを開いてマスクレイヤーを削除するだけで透かしを削除できます。

その後、Canvas が別の Canvas を描画する際に、Canvas が実際に Canvas をそれ自体の上に画像として描画できることがわかったので、次の解決策を思いつきました。

キャンバスに透かしを描く

コンポーネントなので、透かしテキストの透かしは外部から渡されます。

ウォーターマークを描画するためのキャンバスをページに追加する必要はありません。描画が完了したら、DOM 要素を直接返すことができます。返されるのは getContext(2d) を使用して取得したキャンバス インスタンスではなく、DOM 要素であることに注意してください。

ctx.fillStyle はテキストの透明度を示します。 ctx.fillText(this.watermark, 50, 50) は、キャンバス内のテキストの位置を示します。最初の値はテキスト コンテンツ、2 番目の値は x 軸のオフセット、3 番目の値は y 軸のオフセットです。

小道具: {
 透かし:
 タイプ: 文字列、
 デフォルト: 'asing1elife'
 }
},
メソッド: {
 _initWatermark() {
 キャンバスを document.createElement('キャンバス') にします。
 キャンバス幅 = 200
 キャンバスの高さ = 200

 ctx = canvas.getContext('2d') とします。
 ctx.rotate(-18 * Math.PI / 180)
 ctx.font = '14px ヴェダナ'
 ctx.fillStyle = 'rgba(200, 200, 200, .3)'
 ctx.textAlign = '左'
 ctx.textBaseline = '中央'
 ctx.fillText(this.watermark, 50, 50)

 キャンバスを返す
 }
}

コンテンツをレンダリングするキャンバスに透かしを並べて表示します

この方法は、HTML5 キャンバス タイリングのいくつかの方法に基づいています。ctx.rect(0, 0, this.width, this.height) の幅と高さは、_renderPage() 関数で記録されたページ コンテンツ領域の実際の幅と高さです。実際の幅と高さが渡されていれば、キャンバスは透かし画像のサイズとコンテンツ領域のサイズに応じて、x 軸と y 軸の繰り返し回数を自動的に実現します。

メソッド: {
 _renderWatermark() {
 キャンバスを document.querySelector('#pdfCanvas') にします。
 ctx = canvas.getContext('2d') とします。

 // タイル状の透かし let pattern = ctx.createPattern(this._initWatermark(), 'repeat')
 ctx.rect(0, 0, this.width, this.height)
 ctx.fillStyle = パターン
 ctx.fill()
 }
}

ページコンテンツがレンダリングされた後、透かしのレンダリングが再度トリガーされます。

メソッド: {
 // レンダリング page_renderPage () {
 this.pdfDoc.getPage(this.currentPage).then(ページ => {
 // ... 実装コードを省略 page.render({
 キャンバスコンテキスト: ctx,
 ビューポート
 }).promise.then(() => {
 // 透かしをレンダリングする this._renderWatermark()
 })
 })
 }
}

上記は、Vue と PDF.js を統合して PDF プレビューと透かしの追加を実現する詳細です。Vue で PDF プレビューと透かしの追加を実現する詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vue はアップロードされた画像に透かしを追加する機能を実装します
  • Vue で画像と画像の透かしを隠しテキスト情報とともに使用する方法
  • Vueはページに透かし効果を追加する機能を実装します
  • Vueはページ透かし機能を実装
  • Vueを使用して写真をアップロードする3つの方法
  • モバイル端末上のVue+Vantのアップローダーは、画像のアップロード、圧縮、回転の機能を実現します。
  • Vue+elementUI はフォームと画像のアップロードおよび検証機能の例を実装します
  • vue+elementUIは画像アップロード機能を実現します
  • VUEをベースに画像を選択してアップロードし、ページに表示します(画像は削除可能です)
  • Vue はアップロードした画像に透かしを追加できるようになりました (アップグレード版)

<<:  Linux で open-vswitch をインストールおよびアンインストールする方法

>>:  MySQL無料インストールバージョンの設定チュートリアル

推薦する

CentOS 7.6 への MySQL 5.7 GA バージョンのインストール チュートリアル図

目次環境の準備環境の準備mariadbをアンインストールする rpm -qa | grep mari...

jQuery はシャッター効果を実現します (li 配置を使用)

この記事では、ブラインド効果を実現するためのjQueryの具体的なコードを参考までに紹介します。具体...

Centos7のFirewalldファイアウォールの基本コマンドの詳細な説明

1. Linuxファイアウォールの基礎Linux ファイアウォール システムは主にネットワーク層で動...

mysql-joinsの具体的な使用方法

目次結合構文: 1. InnerJOIN: (内部結合) 2. LeftJOIN: (左結合) 3....

CSS の記述基準と順序を共有する [すべての人に使用を推奨]

CSSの記述順序1. 位置属性(位置、上、右、z-index、表示、フロートなど) 2. サイズ(...

MySQL クロステーブルクエリとクロステーブル更新

SQL の基礎知識がある友人は、「クロステーブル クエリ」について聞いたことがあるはずですが、クロス...

VMware に CentOS7 をインストールし (静的 IP アドレスを設定)、Docker コンテナ経由で mySql データベースをインストールする (非常に詳細なチュートリアル)

2 年生から、これらのインストールと設定の仕方を尋ねられました。簡単なチュートリアルを作成し、ここ...

UI を通じて Docker を管理する方法

Docker はますます多くのシナリオで使用されています。コマンドラインツールに慣れていない人にとっ...

WeChatアプレットでSVGアイコンを使用する方法

SVG は、さまざまな利点があるため、近年広く使用されています。残念ながら、WeChat ミニプログ...

Docker で FastDFS ファイル システムを構築する (マルチイメージ チュートリアル)

目次FastDFSについて1. 画像を検索する2. イメージをインストールする3.1. 必要なディレ...

HTML でスクロールバーを使用する際のヒントを共有する

今日、牛南ニュースリリースシステムについて学んでいたとき、牛南先生はスクロールバーに関するいくつかの...

HTML の marquee 属性の詳細な説明

このタグはHTML3.2の一部ではなく、MSIE3以降のカーネルでのみサポートされているため、IEカ...

MySQLデータの挿入、更新、削除の詳細

目次1. 挿入2. 更新3. 削除1. 挿入 顧客に挿入( 顧客.顧客住所、 顧客.cust_cit...

開発者とオペレーターが注目すべき Linux デバッグ ツール [推奨]

システム パフォーマンスの専門家である Brendan D. Gregg 氏は、LinuxCon N...

Linux 占有ポートの強制解放と Linux ファイアウォールのポート開放方法の詳しい説明

nginx、mysql、tomcat などのサービスをインストールするときに、使用する必要があるポー...