Vue做pdf文件预览下载,

  Vue做pdf文件预览下载,

  本文主要介绍如何在Vue中集成Mozilla/PDF.js,实现一个自定义的PDF预览器,并为预览的PDF添加水印。

  

目录

  可以通过插件引入实现效果。

  根据需求选择插件。

  以及安装和引入插件。

  安装和介绍

  初始化插件

  用于呈现内容的Canvas节点用于接收PDFJS实例的对象,监视链接变化并初始化实例。

  呈现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的画布进行两次渲染。尝试后发现“画布渲染上下文2D”上“DrawImage”执行失败的错误:重载解析失败。会被扔。

  所以最后我们选择直接集成pdfjs-dist来完成所有功能。

  

安装和引入插件

  

安装

  纱线添加pdfjs-dist

  

引入

  必须手动指定WorkerSrc,否则将引发设置假工作线程失败的错误。

  虽然这个文件中存在本地目录node _ modules/pdf js-dist/build/pdf.worker.js,但是实际导入时还是会报错,所以只能使用CDN地址下的pdf . worker . js。您可以通过传入PDFJS.version来提高介绍的灵活性

  从“pdfjs-dist”导入*为PDFJS

  PDFJS。globalworkeroptions . workers RC=` https://cdnjs . cloud flare . com/Ajax/libs/pdf . js/$ { pdf js . version }/pdf . worker . js

  

初始化插件

  

用于渲染内容的 canvas 节点

  canvas id=pdfCanvas/canvas

  

用于接收 PDFJS 实例的对象

  道具:{

  PDF文件的实际链接

  url: {

  类型:字符串

  }

  },

  data () {

  返回{

  totalPage: 1,

  //PDFJS实例

  pdfDoc:空

  }

  },

  方法:{

  _initPdf () {

  pdf js . get document(this . URL). promise . then(pdf={

  //文档对象

  this.pdfDoc=pdf

  //总页数

  this.totalPage=pdf.numPages

  //呈现页面

  这个。$nextTick(()={

  这个。_renderPage()

  })

  })

  }

  }

  

监听链接变化并初始化实例

  当外部传递的url有效时,可以触发PDF查看器的初始化功能。

  观察:{

  url (val) {

  如果(!val) {

  返回

  }

  这个。_initPdf()

  }

  },

  

渲染 PDF 内容

  

获取当前页面比率,用于计算内容的实际宽高

  方法:{

  _getRatio (ctx) {

  设DPR=window . devicepixelrratio 1

  设bsr=

  CTX . webkitbackingstorepixelrratio

  CTX . mozbackingstorepixelrratio

  CTX . msbackingstorepixelrratio

  ctx.oBackingStorePixelRatio

  ctx.backingStorePixelRatio

  一个

  返回dpr/bsr

  }

  }

  

渲染当前页面

  page.getViewport({ Scale})中的scale非常关键,直接关系到渲染的内容能否填满整个父容器。所以这里得到的是父容器和页面本身的宽度,父容器宽度/页面宽度之后得到的比值就是实际页面需要放大多少的比值。

  页面。视图是一个数组,里面有四个值,分别是x轴偏移量、y轴偏移量、宽度、高度。要获取真实的宽度,还需要考虑当前页面比率,所以使用page.view[2] *比率计算得出实际宽度。

  data () {

  返回{

  当前页面:1,

  totalPage: 1,

  宽度:0,

  高度:0,

  pdfDoc:空

  }

  },

  方法:{

  _renderPage () {

  这个。pdf文档。获取页面(此。当前页面).然后(page={

  让画布=文档。查询选择器(" # pdfCanvas ")

  let ctx=canvas.getContext(2d )

  //获取页面比率

  让比率=这个. getRatio(ctx)

  //根据页面宽度和视口宽度的比率就是内容区的放大比率

  让dialogWidth=this .$refs[pdfDialog].$el.querySelector( .el-dialog).客户端宽度- 40

  假设页面宽度=page.view[2] *比率

  让比例=对话宽度/页面宽度

  让viewport=page。获取视口({ scale })

  //记录内容区宽高,后期添加水印时需要

  这个。宽度=视口。宽度*比率

  这个。高度=视口。高度*比率

  画布宽度=this .宽度

  画布高度=this .高度

  //缩放比率

  ctx.setTransform(比率,0,0,比率,0,0)

  page.render({

  canvasContext: ctx,

  视口

  }).promise.then(()={})

  })

  }

  }

  

实现页面跳转

  

准备渲染队列,防止渲染顺序混乱

  当触发页面跳转时,会调用_renderQueue()函数,而不是直接调用_renderPage()函数,因为是否开始渲染,要取决于当前是否没有正在被渲染的页面。

  data () {

  返回{

  //是否位于队列中

  渲染:假

  }

  },

  方法:{

  _renderQueue () {

  if (this.rendering) {

  返回

  }

  这个. renderPage()

  }

  }

  

在渲染页面时改变队列状态

  方法:{

  _renderPage () {

  //队列开始

  this.rendering=true

  这个。pdf文档。获取页面(此。当前页面).然后(page={

  //.省略实现代码

  page.render({

  canvasContext: ctx,

  视口

  }).promise.then(()={

  //队列结束

  this.rendering=false

  })

  })

  }

  }

  

实现翻页函数

  data () {

  返回{

  当前页面:1,

  总页数:1

  }

  },

  计算值:{

  //是否首页

  首页(){

  返回this.currentPage=1

  },

  //是否尾页

  lastPage () {

  返回这个。当前页面=这一页。总页数

  },

  },

  方法:{

  //跳转到首页

  firstPageHandler () {

  如果(this.firstPage) {

  返回

  }

  this.currentPage=1

  这个renderQueue()

  },

  //跳转到尾页

  lastPageHandler () {

  if (this.lastPage) {

  返回

  }

  这个。当前页面=这一页。总页数

  这个renderQueue()

  },

  //上一页

  previousPage () {

  如果(this.firstPage) {

  返回

  }

  这个. currentPage

  这个renderQueue()

  },

  //下一页

  nextPage () {

  if (this.lastPage) {

  返回

  }

  这个。当前页面

  这个renderQueue()

  }

  }

  

在页面内容中添加平铺的文字水印

  前端添加水印的方式毋庸置疑都是使用帆布进行绘制。

  最开始找到的方案是准备一个差异作为透明的遮罩层挡在内容区的上层,然后将帆布绘制的水印使用canvas.toDataURL(image/png )导出成Base64格式,作为遮罩层的背景图片进行平铺。虽然可以实现效果,但这种方式只要简单的打开浏览器控制台,删除这个遮罩层就可以去除水印。

  之后在帆布绘制另一个帆布中找到帆布其实是可以将一个帆布作为图片绘制到自身上的,于是有了接下来的方案。

  

绘制作为水印的 canvas

  因为是组件,所以水印的文字水印由外部传入。

  绘制水印的帆布不需要添加到页面中,绘制完成后直接将数字正射影像图元素返回即可,注意,返回的是数字正射影像图元素,而不是使用getContext(2d)获取的画布实例。

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

  道具:{

  水印:{

  类型:字符串,

  默认值:"模拟人生"

  }

  },

  方法:{

  _initWatermark () {

  让画布=文档。createelement(“canvas”);

  画布宽度=200

  画布高度=200

  let ctx=canvas.getContext(2d )

  ctx.rotate(-18 *数学/180).

  ctx.font=14px Vedana

  ctx.fillStyle=rgba(200,200,200,3)

  ctx.textAlign=left

  ctx.textBaseline=middle

  ctx.fillText(this.watermark,50,50)

  返回画布

  }

  }

  

将水印平铺到渲染内容的 canvas 中

  该方法参考自HTML5画布平铺的几种方法,ctx.rect(0,0,this.width,this.height)中的宽度和高度就是在_renderPage()函数中记录的页面内容区的实际宽高。只要将实际宽高传入,画布就会自动根据水印图片的大小和内容区的大小自动实现x轴和y轴的重复次数。

  方法:{

  _renderWatermark () {

  让画布=文档。查询选择器(" # pdfCanvas ")

  let ctx=canvas.getContext(2d )

  //平铺水印

  let pattern=ctx.createPattern(这个. initWatermark(), repeat )

  ctx.rect(0,0,this。宽度,这个。高度)

  ctx.fillStyle=pattern

  ctx.fill()

  }

  }

  

页面内容渲染完成后,再次触发水印渲染

  方法:{

  //渲染页面

  _renderPage () {

  这个。pdf文档。获取页面(此。当前页面).然后(page={

  //.省略实现代码

  page.render({

  canvasContext: ctx,

  视口

  }).promise.then(()={

  //渲染水印

  这个. renderWatermark()

  })

  })

  }

  }

  以上就是某视频剪辑软件集成PDF.js实现便携文档格式预览和添加水印的的详细内容,更多关于某视频剪辑软件实现便携文档格式预览和添加水印的资料请关注我们其它相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: