电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:55日期: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
相關文章:
主站蜘蛛池模板: 杜甫仪器官网|实验室平行反应器|升降水浴锅|台式低温循环泵 | 圣才学习网-考研考证学习平台,提供万种考研考证电子书、题库、视频课程等考试资料 | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | 青岛代理记账_青岛李沧代理记账公司_青岛崂山代理记账一个月多少钱_青岛德辉财税事务所官网 | 成都装修公司-成都装修设计公司推荐-成都朗煜装饰公司 | 电梯装饰-北京万达中意电梯装饰有限公司 | 电机保护器-电动机综合保护器-上海硕吉电器有限公司 | 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | 包装机_厂家_价格-山东包装机有限公司 | 水质传感器_水质监测站_雨量监测站_水文监测站-山东水境传感科技有限公司 | 消泡剂_水处理消泡剂_切削液消泡剂_涂料消泡剂_有机硅消泡剂_广州中万新材料生产厂家 | ET3000双钳形接地电阻测试仪_ZSR10A直流_SXJS-IV智能_SX-9000全自动油介质损耗测试仪-上海康登 | 超声波_清洗机_超声波清洗机专业生产厂家-深圳市好顺超声设备有限公司 | 防爆电机生产厂家,YBK3电动机,YBX3系列防爆电机,YBX4节防爆电机--河南省南洋防爆电机有限公司 | 高压绝缘垫-红色配电房绝缘垫-绿色高压绝缘地毯-上海苏海电气 | 不锈钢法兰-碳钢法兰-法兰盘生产加工厂家-[鼎捷峰]-不锈钢法兰-碳钢法兰-法兰盘生产加工厂家-[鼎捷峰] | 冷却塔厂家_冷却塔维修_冷却塔改造_凉水塔配件填料公司- 广东康明节能空调有限公司 | 北京银联移动POS机办理_收银POS机_智能pos机_刷卡机_收银系统_个人POS机-谷骐科技【官网】 | 压砖机、液压制砖机、静压砖机、环保砖机生产厂家—杜甫机械 | 烘箱-工业烘箱-工业电炉-实验室干燥箱 - 苏州华洁烘箱制造有限公司 | 聚丙烯酰胺PAM-聚合氯化铝PAC-絮凝剂-河南博旭环保科技有限公司 巨野电机维修-水泵维修-巨野县飞宇机电维修有限公司 | 电动不锈钢套筒阀-球面偏置气动钟阀-三通换向阀止回阀-永嘉鸿宇阀门有限公司 | 无锡网站建设_企业网站定制-网站制作公司-阿凡达网络 | 涂层测厚仪_光泽度仪_uv能量计_紫外辐照计_太阳膜测试仪_透光率仪-林上科技 | 消电检公司,消电检价格,北京消电检报告-北京设施检测公司-亿杰(北京)消防工程有限公司 | 诺冠气动元件,诺冠电磁阀,海隆防爆阀,norgren气缸-山东锦隆自动化科技有限公司 | 校车_校车价格_19座幼儿园校车_幼儿园校车_大鼻子校车 | 超声波乳化机-超声波分散机|仪-超声波萃取仪-超声波均质机-精浩机械|首页 | 过跨车_过跨电瓶车_过跨转运车_横移电动平车_厂区转运车_无轨转运车 | 超声波成孔成槽质量检测仪-压浆机-桥梁预应力智能张拉设备-上海硕冠检测设备有限公司 | 航拍_专业的无人机航拍摄影门户社区网站_航拍网 | 免费B2B信息推广发布平台 - 推发网 | IWIS链条代理-ALPS耦合透镜-硅烷预处理剂-上海顶楚电子有限公司 lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | SMC-SMC电磁阀-日本SMC气缸-SMC气动元件展示网 | 氧氮氢联合测定仪-联测仪-氧氮氢元素分析仪-江苏品彦光电 | 超声骨密度仪,双能X射线骨密度仪【起草单位】,骨密度检测仪厂家 - 品源医疗(江苏)有限公司 | 广西绿桂涂料--承接隔热涂料、隔音涂料、真石漆、多彩仿石漆等涂料工程双包施工 | 江苏大隆凯科技有限公司 | 玉米深加工设备-玉米深加工机械-新型玉米工机械生产厂家-河南粮院机械制造有限公司 | 青州开防盗门锁-配汽车芯片钥匙-保险箱钥匙-吉祥修锁店 | 升降机-高空作业车租赁-蜘蛛车-曲臂式伸缩臂剪叉式液压升降平台-脚手架-【普雷斯特公司厂家】 |