成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

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

瀏覽:13日期: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
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩午夜黄色| 青青草精品视频| 午夜精品视频| 日韩福利视频导航| 精品国精品国产| 蜜桃视频一区二区三区在线观看| 亚洲高清免费| 欧美激情在线一区二区| 成人免费高清在线| 欧美一三区三区四区免费在线看 | 国产日本精品| 亚洲欧美成人一区二区三区| 狠狠色狠狠色综合人人| 国产片一区二区三区| 日韩一区二区三区四区| 国产一区二区三区在线观看免费 | 精品理论电影在线| 欧美日韩一区二区在线视频| 国产日本精品| 紧缚奴在线一区二区三区| 亚洲成色精品| 一区二区在线免费| 国产亚洲欧美一区二区| 亚洲女人****多毛耸耸8| 欧美激情无毛| 国产精品久久99| 亚洲午夜视频| 亚洲精品免费在线观看| 国产精品乱码| 亚洲图片欧美综合| 国产亚洲精品超碰| 欧美精品高清视频| 在线一区二区三区四区五区| 一区二区三区久久网 | 欧美激情在线看| 欧美精品一区二区三区高清aⅴ| 欧美高清dvd| 欧美性videosxxxxx| 免播放器亚洲| 国产精品久久久对白| 在线成人黄色| 国产精品xnxxcom| 欧美午夜一区二区福利视频| 成人黄色av网站在线| 国产呦精品一区二区三区网站| 久久影院午夜片一区| 久久精品久久精品| 国产精品日本| 日韩精品乱码免费| 欧美人体做爰大胆视频| 丁香网亚洲国际| 国产日韩欧美a| 韩国av一区| 亚洲午夜一区二区| 欧美在线视频全部完| 国产激情视频一区二区三区欧美| 日韩一区二区三区免费看| 国产91高潮流白浆在线麻豆| 精品成人一区二区| 欧美精品一区二区视频| 亚洲激情六月丁香| 久久综合狠狠| 激情综合五月天| 久久丝袜美腿综合| 亚洲精品婷婷| 美女网站在线免费欧美精品| 欧美久久久久中文字幕| 成人国产在线观看| 18成人在线观看| 在线视频欧美区| 成人18视频日本| 亚洲欧美日韩国产综合在线| 91久久久免费一区二区| 岛国一区二区在线观看| 日本一区二区不卡视频| 亚洲黄色大片| 三级成人在线视频| 6080yy午夜一二三区久久| 色综合咪咪久久| 一区二区三区日韩欧美精品| 在线精品视频一区二区三四| 99视频一区二区| 亚洲欧美另类小说视频| 欧美午夜片在线观看| av电影天堂一区二区在线观看| 中文字幕日韩欧美一区二区三区| 国产精品最新自拍| 国产一区二区影院| 亚洲日本丝袜连裤袜办公室| 一本大道av伊人久久综合| 国产福利一区二区三区视频在线| 国产欧美精品一区aⅴ影院| 性色一区二区| 国产成人亚洲精品狼色在线| 亚洲欧美日韩国产成人精品影院 | 在线免费一区三区| 97久久超碰精品国产| 亚洲午夜三级在线| 精品免费视频.| 久久av一区二区| 国产乱子伦视频一区二区三区| 亚洲欧洲国产日本综合| 91国产视频在线观看| 欧美久久一级| 久久国产精品色| 亚洲图片你懂的| 884aa四虎影成人精品一区| 亚洲激情不卡| 国产激情视频一区二区在线观看| 亚洲色欲色欲www| 欧美福利电影网| 国产精品一区二区你懂得| 福利视频网站一区二区三区| 首页亚洲欧美制服丝腿| 国产欧美日韩在线| 欧美日韩亚洲不卡| 国产精品视频| eeuss鲁片一区二区三区在线看| 亚洲午夜影视影院在线观看| 久久蜜臀精品av| 欧美亚洲自拍偷拍| 亚洲欧洲另类| jizzjizzjizz欧美| 国内成人免费视频| 亚洲综合另类小说| 国产无遮挡一区二区三区毛片日本| 欧洲人成人精品| 亚洲裸体俱乐部裸体舞表演av| av动漫一区二区| 国模无码大尺度一区二区三区| 一区二区日韩av| 欧美激情中文不卡| 精品国产一区二区三区av性色| 色综合久久88色综合天天免费| 欧美激情亚洲| 国产精品正在播放| 三级久久三级久久久| 亚洲蜜臀av乱码久久精品蜜桃| 欧美va亚洲va香蕉在线| 91极品视觉盛宴| 日韩视频在线观看国产| 91毛片在线观看| 国产乱码精品一区二区三区av | 欧美三级韩国三级日本三斤| 亚洲一区图片| 狠狠爱成人网| 欧美在线视屏| 成人晚上爱看视频| 麻豆精品一区二区三区| 亚洲国产欧美在线| 亚洲黄色小视频| 中文字幕制服丝袜一区二区三区 | 欧美三级视频在线播放| 久久一综合视频| 91久久在线| 欧美日韩免费观看一区=区三区| 成人av在线观| 成人性生交大片免费| 国产激情一区二区三区| 精品亚洲国产成人av制服丝袜| 日韩黄色免费网站| 亚洲午夜av在线| 一区二区三区在线免费播放| 亚洲色图制服诱惑| 中文字幕在线一区| 国产精品毛片a∨一区二区三区| 国产亚洲综合av| 久久免费精品国产久精品久久久久| 欧美蜜桃一区二区三区| 在线观看免费一区| 久久资源在线| 免费在线一区二区| 亚洲一区国产| 99亚洲一区二区| 亚洲欧洲久久| 99国内精品| 国产日韩一区二区三区| 国产欧美综合一区二区三区| 亚洲日韩视频| 日韩视频一区二区三区在线播放免费观看| 亚洲午夜激情在线| 亚洲成色精品| 中文国产一区| 日韩天堂av| 在线视频免费在线观看一区二区| 国产精品分类| 视频在线观看一区| 亚洲成av人片一区二区| 亚洲最大的成人av| 亚洲免费av网站| 一区二区欧美视频| 首页国产丝袜综合| 精品一区二区日韩| 国产精品系列在线播放| 国产精品一区二区你懂的| 国产 欧美在线| 99精品视频在线观看| 91蜜桃视频在线| 好吊一区二区三区| 一区二区三区三区在线|