当前位置:   article > 正文

Vue3预览并打印PDF的两种方法_vue-pdf-embed

vue-pdf-embed

项目场景:后台接口请求数据,返回PDF文档的链接(即pdf文件在服务器上的存放路径),在vue3页面可预览和打印该PDF。

在之前的Vue2项目中,预览并打印PDF用的是vue-pdf这个插件,但在vue3中是不支持的,只能换个插件了,于是经过测试,也踩了一些坑,总结了以下两种方法:

方法一:使用vue-pdf-embed pdfjs-dist

①首先,安装这两个插件依赖

  1. pnpm install vue-pdf-embed
  2. pnpm install pdfjs-dist2.0.943

当时我在安装pdfjs-dist时遇到了问题 ,我没有指定版本号,控制台报错,翻了一些文章,有博主建议安装2.0.943版本,于是又重新输入命令,安装了这个版本,就一切正常了

②页面中写相关代码

  1. // 引入插件
  2. import VuePdfEmbed from 'vue-pdf-embed'
  3. import * as pdfjsLib from 'pdfjs-dist'
  4. //定义
  5. const state = reactive({
  6. source: '', // pdf文件地址
  7. pageNum: 0, // 当前页面
  8. scale: 1, // 缩放比例
  9. numPages: 0 // 总页数
  10. })
  11. const scale = computed(() => `transform:scale(${state.scale})`)
  1. <div>
  2. // 操作按钮
  3. <div class="page-tool">
  4. <div class="page-tool-item" @click="lastPage">上一页</div>
  5. <div class="page-tool-item" @click="nextPage">下一页</div>
  6. <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
  7. <div class="page-tool-item" @click="pageZoomOut">放大</div>
  8. <div class="page-tool-item" @click="pageZoomIn">缩小</div>
  9. </div>
  10. //pdf预览
  11. <vue-pdf-embed ref='pdf' :source="state.source" :style="scale" :page="state.pageNum" class="vue-pdf-embed" />
  12. </div>
  1. <script setup>
  2. onMounted(()=>{
  3. // 首先请求接口,获取pdf存放地址,赋值给pdfUrl(此处省略请求代码)
  4. // 拿到pdf路径后,执行下面的函数
  5. getPdfUrl(pdfUrl)
  6. })
  7. function getPdfUrl(data){
  8. state.source = data
  9. pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.js'
  10. const loadingTask = pdfjsLib.getDocument(data)
  11. loadingTask.promise.then(pdf => {
  12. state.numPages = pdf.numPages
  13. })
  14. }
  15. // 上一页
  16. function lastPage() {
  17. if (state.pageNum > 1) {
  18. state.pageNum -= 1
  19. }
  20. }
  21. // 下一页
  22. function nextPage() {
  23. if (state.pageNum < state.numPages) {
  24. state.pageNum += 1
  25. }
  26. }
  27. // 放大
  28. function pageZoomOut() {
  29. if (state.scale < 2) {
  30. state.scale += 0.1
  31. }
  32. }
  33. // 缩小
  34. function pageZoomIn() {
  35. if (state.scale > 1) {
  36. state.scale -= 0.1
  37. }
  38. }
  39. </script>

为了好看一些,我给操作按钮写了样式

  1. <style lang="scss" scoped>
  2. .page-tool {
  3. display: flex;
  4. position: absolute;
  5. top: 5px;
  6. left: 50%;
  7. z-index: 100;
  8. transform: translateX(-50%);
  9. align-items: center;
  10. background: rgb(66 66 66);
  11. color: white;
  12. border-radius: 19px;
  13. cursor: pointer;
  14. justify-content: center;
  15. font-size: 15px;
  16. }
  17. .page-tool-item {
  18. padding: 4px 10px;
  19. cursor: pointer;
  20. }
  21. </style>

 最终的实现效果:

打印:

  1. const { proxy } = getCurrentInstance()
  2. <div @click='print'>打印</div>
  3. <script setup>
  4. function print(){
  5. proxy.$refs['pdf'].print()
  6. }
  7. </script>

 方法二:使用pdfjs-dist,canvas渲染,pdf.js打印

  说明:pdf.js可以打印canvas数据,所以选择这个插件

①首先,安装依赖

pnpm install pdfjs-dist

 安装之后,在项目的node_modules文件夹里,找到pdfjs-dist ->build->pdf.worker.js文件,拷贝出来放到public根目录下,接着找到pdfjs-dist ->cmaps文件夹,拷贝一下放到public->static文件夹里,如下图所示:

②下载print.js放入项目中,在需要使用的页面,引入方法,然后方法调用

具体我是参考的这篇博文:前端使用print.js实现打印_printjs_@我不认识你的博客-CSDN博客

③代码实现

  1. // 打印按钮
  2. <div @click="print">打印</div>
  3. //pdf预览显示
  4. <div>
  5. <div id="printDom" ref="printDom">
  6. <div v-for="item in state.numPages" :key="item">
  7. <canvas :id="`pdfCanvas-${item}`" :ref="`pdfCanvas-${item}`" />
  8. </div>
  9. </div>
  10. </div>
  11. <script setup>
  12. import * as pdfjsLib from 'pdfjs-dist' //引入pdfjs-dist
  13. import Print from '@/assets/js/print' //引入print.js
  14. const { proxy } = getCurrentInstance()
  15. const state = reactive({
  16. pageNum: 0, // 当前页面
  17. scale: 1, // 缩放比例
  18. numPages: 0, // 总页数
  19. pdfCtx: null // pdf对象
  20. })
  21. onMounted(()=>{
  22. // 请求服务接口,获取pdf存放地址,赋值给pdfUrl变量(此处省略请求代码)
  23. // pdfUrl获取到之后,接着执行以下代码
  24. pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.js'
  25. const loadingTask = pdfjsLib.getDocument({
  26. url: pdfUrl, //这里的pdfUrl即pdf的链接地址
  27. cMapUrl: '../../../../static/cmaps/',
  28. cMapPacked: true
  29. })
  30. loadingTask.promise.then(pdf => {
  31. // console.log('页数', pdf.numPages)
  32. state.numPages = pdf.numPages
  33. state.pdfCtx = pdf
  34. nextTick(() => {
  35. renderPdf()
  36. })
  37. })
  38. })
  39. const renderPdf = (num = 1) => {
  40. state.pdfCtx.getPage(num).then(page => {
  41. const canvas = document.getElementById(`pdfCanvas-${num}`)
  42. const ctx = canvas.getContext('2d')
  43. const viewport = page.getViewport(1.6)
  44. canvas.height = viewport.height
  45. canvas.width = viewport.width
  46. page.render({
  47. canvasContext: ctx,
  48. viewport: viewport
  49. })
  50. if (num < state.numPages) {
  51. renderPdf(num + 1)
  52. }
  53. })
  54. }
  55. //打印
  56. function print(){
  57. Print(proxy.$refs['printDom'])
  58. }
  59. </script>

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/305621
推荐阅读