日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Vue 集成 PDF.js 實現 PDF 預覽和添加水印的步驟

瀏覽:17日期:2022-10-09 14:01:04
實現效果

Vue 集成 PDF.js 實現 PDF 預覽和添加水印的步驟

可用插件介紹

Mozilla 提供了 PDF.js 和pdfjs-dist ,兩者的區別如下:

PDF.js ,一個完整的 PDF 查看器,可以直接使用其提供的 viewer.html 查看 PDF 內容,包含完整樣式和相關功能。優點是快速集成,不需要自己實現查看器的功能和樣式。缺點是如果要自定義樣式和功能,反而會很麻煩。 pdfjs-dist ,PDF.js 的預購建版本,只包含 PDF 內容的渲染功能,需要自己實現查看器的樣式和相關功能。

Vue 官方插件庫 Awesome Vue.js 推薦的vue-pdf 就是對 pdfjs-dist 進行了封裝實現,一般情況下使用 vue-pdf 即可快速實現 PDF 的預覽效果。

根據需求進行插件選型

我們的需求是在現有頁面中實現 PDF 預覽的同時,在 PDF 內容上添加水印。

PDF.js 這種完整版的查看器顯得過于臃腫,而 vue-pdf 雖然可以快速實現預覽效果,但在添加水印時需要對顯示 PDF 的 canvas 進行二次渲染,經過嘗試后發現會拋出 Failed to execute ’drawImage’ on ’CanvasRenderingContext2D’: Overload resolution failed. 的錯誤。

所以最后選擇直接集成 pdfjs-dist 來完成全部功能

安裝和引入插件安裝

yarn add pdfjs-dist引入

必須手動指定 workerSrc ,不然會拋出 Setting up fake worker failed 的錯誤。

雖然本地目錄 node_modules/pdfjs-dist/build/pdf.worker.js 存在該文件,但實際引入時依舊會報錯,所以只能使用 CDN 地址下的 pdf.worker.js 。可以通過傳入 PDFJS.version 來提高引入的靈活性。

import * as PDFJS from ’pdfjs-dist’PDFJS.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDFJS.version}/pdf.worker.js`初始化插件用于渲染內容的 canvas 節點

<canvas id='pdfCanvas'></canvas>用于接收 PDFJS 實例的對象

props: { // PDF 文件的實際鏈接 url: { type: String }},data () { return { totalPage: 1, // PDFJS 實例 pdfDoc: null }},methods: { _initPdf () { PDFJS.getDocument(this.url).promise.then(pdf => { // 文檔對象 this.pdfDoc = pdf // 總頁數 this.totalPage = pdf.numPages // 渲染頁面 this.$nextTick(() => { this._renderPage() }) }) }}監聽鏈接變化并初始化實例

當外部傳入的 url 有效時,就可以觸發 PDF 查看器的初始化函數

watch: { ’url’ (val) { if (!val) { return } this._initPdf() }},渲染 PDF 內容獲取當前頁面比率,用于計算內容的實際寬高

methods: { _getRatio (ctx) { let dpr = window.devicePixelRatio || 1 let bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1 return dpr / bsr }}渲染當前頁面

page.getViewport({ scale }) 中的 scale 非常關鍵,直接關系到渲染出來的內容能不能撐滿整個父容器,所以這里分別獲取了父容器和頁面本身的寬度,父容器寬度 / 頁面寬度 后得出的比率就是實際頁面需要放大多少的比率。

page.view 是一個數組,里面有四個值,分別是 x軸偏移量、y軸偏移量、寬度、高度。 要獲取真實的寬度,還需要考慮當前頁面比率,所以使用 page.view[2] * ratio 計算得出實際寬度。

data () { return { currentPage: 1, totalPage: 1, width: 0, height: 0, pdfDoc: null }},methods: { _renderPage () { this.pdfDoc.getPage(this.currentPage).then(page => { let canvas = document.querySelector(’#pdfCanvas’) let ctx = canvas.getContext(’2d’) // 獲取頁面比率 let ratio = this._getRatio(ctx) // 根據頁面寬度和視口寬度的比率就是內容區的放大比率 let dialogWidth = this.$refs[’pdfDialog’].$el.querySelector(’.el-dialog’).clientWidth - 40 let pageWidth = page.view[2] * ratio let scale = dialogWidth / pageWidth let viewport = page.getViewport({ scale }) // 記錄內容區寬高,后期添加水印時需要 this.width = viewport.width * ratio this.height = viewport.height * ratio canvas.width = this.width canvas.height = this.height // 縮放比率 ctx.setTransform(ratio, 0, 0, ratio, 0, 0) page.render({ canvasContext: ctx, viewport }).promise.then(() => {}) }) }}實現頁面跳轉準備渲染隊列,防止渲染順序混亂

當觸發頁面跳轉時,會調用 _renderQueue() 函數,而不是直接調用 _renderPage() 函數,因為是否開始渲染,要取決于當前是否沒有正在被渲染的頁面。

data () { return { // 是否位于隊列中 rendering: false }},methods: { _renderQueue () { if (this.rendering) { return } this._renderPage() }}在渲染頁面時改變隊列狀態

methods: { _renderPage () { // 隊列開始 this.rendering = true this.pdfDoc.getPage(this.currentPage).then(page => { // ... 省略實現代碼 page.render({ canvasContext: ctx, viewport }).promise.then(() => { // 隊列結束 this.rendering = false }) }) }}實現翻頁函數

data () { return { currentPage: 1, totalPage: 1 }},computed: { // 是否首頁 firstPage () { return this.currentPage <= 1 }, // 是否尾頁 lastPage () { return this.currentPage >= this.totalPage },},methods: { // 跳轉到首頁 firstPageHandler () { if (this.firstPage) { return } this.currentPage = 1 this._renderQueue() }, // 跳轉到尾頁 lastPageHandler () { if (this.lastPage) { return } this.currentPage = this.totalPage this._renderQueue() }, // 上一頁 previousPage () { if (this.firstPage) { return } this.currentPage-- this._renderQueue() }, // 下一頁 nextPage () { if (this.lastPage) { return } this.currentPage++ this._renderQueue() }}在頁面內容中添加平鋪的文字水印

前端添加水印的方式毋庸置疑都是使用 canvas 進行繪制。

最開始找到的方案是準備一個 div 作為透明的遮罩層擋在內容區的上層,然后將 canvas 繪制的水印使用 canvas.toDataURL(’image/png’) 導出成 Base64 格式,作為遮罩層的背景圖片進行平鋪。 雖然可以實現效果,但這種方式只要簡單的打開瀏覽器控制臺,刪除這個遮罩層就可以去除水印。

之后在 Canvas 繪制另一個 Canvas 中找到 canvas 其實是可以將一個 canvas 作為圖片繪制到自身上的,于是有了接下來的方案。

繪制作為水印的 canvas

因為是組件,所以水印的文字 watermark 由外部傳入。

繪制水印的 canvas 不需要添加到頁面中,繪制完成后直接將 DOM 元素返回即可,注意,返回的是 DOM 元素 ,而不是使用 getContext(2d) 獲取的畫布實例。

ctx.fillStyle 表示文字的透明度。 ctx.fillText(this.watermark, 50, 50) 表示文字在畫布中的位置,第一個值是文字內容,第二個值是 x軸偏移量,第三個值是 y軸偏移量。

props: { watermark: { type: String, default: ’asing1elife’ }},methods: { _initWatermark () { let canvas = document.createElement(’canvas’); canvas.width = 200 canvas.height = 200 let ctx = canvas.getContext(’2d’) ctx.rotate(-18 * Math.PI / 180) ctx.font = ’14px Vedana’ ctx.fillStyle = ’rgba(200, 200, 200, .3)’ ctx.textAlign = ’left’ ctx.textBaseline = ’middle’ ctx.fillText(this.watermark, 50, 50) return canvas }}將水印平鋪到渲染內容的 canvas 中

該方法參考自 HTML5 canvas 平鋪的幾種方法 ,ctx.rect(0, 0, this.width, this.height) 中的 width 和 height 就是在 _renderPage() 函數中記錄的頁面內容區的實際寬高。只要將實際寬高傳入,canvas 就會自動根據水印圖片的大小和內容區的大小自動實現 x軸和 y軸的重復次數。

methods: { _renderWatermark () { let canvas = document.querySelector(’#pdfCanvas’) let ctx = canvas.getContext(’2d’) // 平鋪水印 let pattern = ctx.createPattern(this._initWatermark(), ’repeat’) ctx.rect(0, 0, this.width, this.height) ctx.fillStyle = pattern ctx.fill() }}頁面內容渲染完成后,再次觸發水印渲染

methods: { // 渲染頁面 _renderPage () { this.pdfDoc.getPage(this.currentPage).then(page => { // ... 省略實現代碼 page.render({ canvasContext: ctx, viewport }).promise.then(() => { // 渲染水印 this._renderWatermark() }) }) }}

以上就是Vue 集成 PDF.js 實現 PDF 預覽和添加水印的的詳細內容,更多關于vue 實現 PDF 預覽和添加水印的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美日韩国产在线观看网站| 在线看片不卡| 久久婷婷一区| 亚洲h色精品| 欧美日韩在线观看视频小说| 激情欧美一区二区三区| 悠悠资源网久久精品| 美女国产一区| 欧美日本二区| 国产在线视频欧美一区| 日韩在线观看| 亚洲欧美日本日韩| 欧美日韩亚洲一区二区三区在线| 国产精品中文| 激情久久一区二区| 999国产精品永久免费视频app| 欧美福利一区| 国产综合亚洲精品一区二| 日韩影院精彩在线| 欧美日韩国产一区二区在线观看| 久久久国产精品网站| 日韩毛片视频| 亚洲欧洲一区二区天堂久久| 中文字幕亚洲精品乱码| 国产精品白丝一区二区三区| 中文另类视频| 亚洲精品九九| www在线观看黄色| 日韩精品一二三| 精品国产成人| 石原莉奈在线亚洲二区| 精品一区二区三区免费看| 亚洲成人一区在线观看| 天堂成人免费av电影一区| 国产精品久久久久av蜜臀| 久久狠狠婷婷| 国产日韩一区二区三区在线| 欧美日韩一二| 国产精品综合| 亚洲欧美激情诱惑| 国产一区二区三区四区| 午夜一区在线| 精品日本视频| 日av在线不卡| 日本一二区不卡| 麻豆亚洲精品| 日韩欧美精品一区| 色婷婷成人网| 久久九九国产| 国产极品久久久久久久久波多结野 | 精品国产一级| 日韩中文字幕麻豆| 秋霞影院一区二区三区| 国产精品天天看天天狠| 免费日韩精品中文字幕视频在线| 国内在线观看一区二区三区 | 日韩精品一级中文字幕精品视频免费观看 | 日韩精品一区二区三区中文 | 日产欧产美韩系列久久99| 久久福利在线| 欧美精品激情| 久久青青视频| 久久精品99国产国产精| 国产综合精品| 激情黄产视频在线免费观看| 日韩精品免费视频人成| 激情综合亚洲| 国产+成+人+亚洲欧洲在线| 亚洲资源网站| 欧美精品黄色| 日韩欧美字幕| 国产成人精品三级高清久久91| 97久久亚洲| 亚洲一区二区免费在线观看| 99精品综合| 日本不卡免费高清视频在线| 欧美a一区二区| 久久精品99国产国产精| 日韩欧美激情电影| 蜜臀av性久久久久蜜臀aⅴ流畅| 激情视频一区二区三区| 人人香蕉久久| 国产在线|日韩| 日本久久成人网| 精品三级久久| 欧美aa一级| 麻豆mv在线观看| 精品国产乱码久久久久久1区2匹| 国产精品对白| 国产精品片aa在线观看| 国产亚洲观看| 欧美日韩伊人| 久久成人福利| 国产专区精品| 国产一区2区在线观看| 激情久久99| 中文在线免费视频| 鲁鲁在线中文| 日韩亚洲一区在线| 成人精品中文字幕| 欧美高清一区| 日av在线不卡| 97精品久久| 国产精品对白久久久久粗| 欧美一级久久| 国产伦精品一区二区三区视频 | 性欧美69xoxoxoxo| 欧美精品一二| 国产婷婷精品| 亚洲一区二区三区四区电影 | 夜夜嗨网站十八久久| 国产精品毛片| 视频在线在亚洲| 日韩亚洲精品在线观看| 欧美性www| 精品视频高潮| 日本久久成人网| 丝袜美腿亚洲色图| 国产日韩视频| 中文字幕高清在线播放| 婷婷亚洲五月色综合| 亚洲专区视频| 免费在线亚洲| 天堂资源在线亚洲| 亚洲精品自拍| 日韩精品免费观看视频| 久久精品欧洲| 91精品成人| 欧美自拍一区| 日韩一区亚洲二区| 免费一区二区视频| 精品国产一区二区三区av片| 久久精品二区三区| 亚洲精品激情| 国产精品毛片久久| 模特精品在线| 久久av资源| 午夜久久福利| 国产精品草草| 好吊一区二区三区| 日韩中文字幕无砖| 国产日韩电影| 亚洲尤物av| 激情国产在线| 亚洲欧美日本国产| av在线最新| 日韩中文字幕| 欧美精品日日操| 一级成人国产| 伊人久久在线| 青青草91视频| 99久久www免费| 国产精品xvideos88| 91精品1区| 九九99久久精品在免费线bt| 欧美另类专区| 国产精品99一区二区三区| 亚洲人成在线影院| 日韩三区免费| 国产欧美日韩在线一区二区 | 国产精品成人自拍| 香蕉久久99| 日本不卡视频一二三区| 午夜欧美巨大性欧美巨大| 婷婷综合国产| 国内自拍视频一区二区三区| 中文字幕日韩亚洲| 播放一区二区| 久久久国产精品入口麻豆| 蜜臀久久久99精品久久久久久| 麻豆mv在线观看| 欧美精品国产| 综合激情一区| 9国产精品视频| 日韩中文在线电影| 久久精品国产亚洲一区二区三区| 日韩**一区毛片| 亚洲一区区二区| 国产在线|日韩| 国产视频一区免费看| 中文在线а√在线8| 亚洲a成人v| 午夜久久福利| 日本蜜桃在线观看视频| 国产精品激情电影| 一区二区不卡| 亚洲成人一区| 成人在线免费观看91| 国产欧美日韩一区二区三区四区 | 亚洲女同一区| 国产一区二区三区不卡视频网站 | 中文字幕亚洲精品乱码| 在线一区视频观看| 国产伊人久久| 国产精品中文字幕亚洲欧美| 日韩精品免费视频一区二区三区| 日韩制服丝袜av| 免费观看在线色综合| 久久婷婷亚洲| 日韩欧美综合|