js 打印方案

前言
  • 打印功能的实现方式有很多种,在此将通过 print.js 来介绍打印功能的实现以及实现过程中遇到的一些问题
一、仅打印图片
  • npm 安装
npm install print-js --save
  • npm 安装时将库导入项目
import printJS from 'print-js'
示例
  • HTML
<div ref="printMe" id="printMe">
  <img class="print-file" slot="cover" alt="example" :src="url" />
</div>
  • js
print({
  printable: this.$refs.printMe, // 要打印的id / ref。
  documentTitle: '审核材料', // 文档标题
  type: 'html', // 可以是 html 、pdf、image, json 等。
  targetStyles: ['*'], // 这样设置继承了页面要打印元素原有的css属性。
  ignoreElements: [], // 传入要打印的div中的子元素id,使其不打印
  onLoadingStart: () => {
    console.log('loading-start')
  },
  onLoadingEnd: () => {
    console.log('loading-end')
  },
  onPrintDialogClose: () => {
    console.log('print-dialog-close')
  },
  onError: e => {
    console.log('打印失败')
  },
})

本示例以打印 HTML 为例,print.js 还可以打印 pdf、image, json,默认打印 PDF

二、打印图片和 PDF

如果我们要同时打印含有图片和 PDF,有两种方案

  1. 使用 canvas 把 PDF 转为图片
  2. 引入 vue-pdf 标签来做 PDF 的展示
  • vue-pdf 的优点:不用自己转图片,缺点:虽然可以实现功能,但是打出来比较模糊,图片质量不高,客户接受程度太低。在此我们选择第一种方案
第一步:先下载 pdfjs,网址:PDF 下载地址,把 pdf.js、pdf.worker.js 文件放到项目中,然后在需要打印的页面引入
import * as pdfjsLib from './pdfjs/build/pdf.js'
第二步:html 代码添加一行代码,canvas 用来绘图
<canvas id="the-canvas" style="display: none"></canvas>
  • HTML
<div ref="printMe" id="printMe">
  <div v-for="(item, index) in array" :key="index">
    <img class="print-file" slot="cover" alt="example" :src="item.url" />
  </div>
</div>
<canvas id="the-canvas" style="display: none"></canvas>
<button @click="printFile">打印</button>
  • js
// pdf 转图片
 async changePdfToImg (url) {
      const _this = this
      let imgArr = []
      pdfjsLib.workerSrc = 'pdf.worker.js'
      let loadingTask = pdfjsLib.getDocument(url)
      let res = await loadingTask.promise
      let pageNum = res.numPages
      for (let i = 1; i <= pageNum; i++) {
        let page = await res.getPage(i)
        let scale = 4
        let viewport = page.getViewport(scale)
        let canvas = document.createElement('canvas')
        let context = canvas.getContext('2d')
        canvas.height = viewport.height
        canvas.width = viewport.width
        let renderContext = {
          canvasContext: context,
          viewport: viewport,
        }
        await page.render(renderContext)
        let imgUrl = canvas.toDataURL('image/jpeg', 1) //转换为base64
        if (imgUrl) {
          imgArr[i - 1] = imgUrl
        }
        //pdf全部画完结束后操作
        if (imgArr.length == pageNum && !_this.isEmpty(imgArr)) {
          let canvas2 = document.getElementById('the-canvas')
          let context2 = canvas2.getContext('2d')
          canvas2.height = viewport.height * pageNum
          canvas2.width = viewport.width
          let count = 0
          for (let j = 0; j < imgArr.length; j++) {
            let IMG = new Image()
            IMG.src = imgArr[j]
            IMG.width = viewport.width
            IMG.height = viewport.height
            IMG.onload = function () {
              context2.drawImage(IMG, 0, viewport.height * j)
              count++ //确保所有img渲染结束后操作
              if (count == pageNum) {
                let canvas = document.getElementById('the-canvas')
                //赋值给img
                _this.imgUrl = canvas.toDataURL('image/jpeg')
              }
            }
          }
        }
      }
      return imgArr
    },
async printFile () {
  const array = []
  list.forEach((i, num) => {
      const obj = {
        url: '',
      }
      if (i.url.indexOf('.pdf') === -1) {
        obj.url = i.url
        array.push(obj)
      } else {
        this.changePdfToImg(i.url).then(res => {
          for (let n = 0; n < res.length; n++) {
            const obj = {
              url: res[n],
            }
            array.push(obj)
          }
        })
      }
    })
  await this.printFn(array)
}
print({
  printable: this.$refs.printMe, // 要打印的id / ref。
  documentTitle: '审核材料', // 文档标题
  type: 'html', // 可以是 html 、pdf、image, json 等。
  targetStyles: ['*'], // 这样设置继承了页面要打印元素原有的css属性。
  ignoreElements: [], // 传入要打印的div中的子元素id,使其不打印
  onLoadingStart: () => {
    console.log('loading-start')
  },
  onLoadingEnd: () => {
    console.log('loading-end')
  },
  onPrintDialogClose: () => {
    console.log('print-dialog-close')
  },
  onError: e => {
    console.log('打印失败')
  },
})

注意

1.toDataURL方法参数

canvas.toDataURL('image/jpeg', 1)
toDataURL(type?: string, quality?: any): string;
  • toDataURL 的第二个参数(图片质量)在平常使用中容易被忽略,如果图像格式支持可变质量(如“图像/jpeg”),则质量字段是 0.0 到 1.0(包括 0.0 到 1.0)范围内的数字,表示生成图像的所需质量级别。级别越高则越清晰,生成的文件也越大

2. <object>、<embed>标签可以直接在页面上预览 PDF 文件,兼容性比较差,safair、IE 上运行没问题,360,火狐,谷歌等浏览器均不支持

3. 使用 iframe 引入 pdf 文件,使用网络资源高度无法撑开,无法通过 getElementById()方法来获取元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值