vue页面导出pdf

vue页面导出pdf

  1. 下载依赖
    yarn add html2canvas // 将页面html转换成图片
    yarn add jspdf // 将图片生成pdf
  2. 定义全局函数,创建htmlToPdf.js文件
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.getPdf = function (idStr, title) {
      html2Canvas(document.querySelector('#' + idStr), {
        // allowTaint: true,
        useCORS: true
      }).then(function (canvas) {
        const contentWidth = canvas.width
        const contentHeight = canvas.height
        // 一页pdf显示html页面生成的canvas高度;
        const pageHeight = contentWidth / 592.28 * 841.89
        // 生成pdf的html页面高度
        let leftHeight = contentHeight
        // 页面偏移
        let position = 0
        // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        const imgWidth = 595.28
        const imgHeight = 592.28 / contentWidth * contentHeight
        // canvas.crossOrigin="anonymous";
        const pageData = canvas.toDataURL('image/jpeg', 1.0)

        const PDF = new JsPDF('', 'pt', 'a4')
        // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        // 当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
              // 避免添加空白页
              PDF.addPage()
            }
          }
        }
        PDF.save(title + '.pdf')
      })
    }
  }
}

  1. 在main.js中使用
import htmlToPdf from '@/components/htmlToPdf/htmlToPdf'

Vue.use(htmlToPdf)
  1. 在使用的页面调用方法
<template>
  <div class="row" id="pdfDom" style="padding-top: 55px;background-color:#fff;">
    //pdf想要展示的内容
  </div>
</template>
<script>
export default {
  data () {
    return {}
  },
  method: {
    // 点击调用方法
    htmlToPdf () {
      this.getPdf('pdfDom', '巡检任务报表')
    },
  }
}
</script>

问题1:转pdf,所以会存在导出模糊的情况

dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
scale: 4, // 按比例增加分辨率

问题2:导出的pdf页边距的问题

var a4Width = 555.28 // 原A4宽592因为要设置边距 20 ,这里要减掉 40
var a4Height = 801.89 // 原A4高841因为要设置边距 20 ,这里要减掉 40
// 设置两边边距 20 20
pdf.addImage(pageData, 'JPEG', 20,20, a4Width, a4Width / canvas.width * leftHeight)

问题三:滚动影响

Vue.prototype.getPdfFromHtml = function (ele, pdfFileName) {
  document.documentElement.scrollTop = 0
  document.body.scrollTop = 0
  html2Canvas(ele, {
    windowWidth: document.body.scrollWidth,
    windowHeight: document.body.scrollHeight,
  }).then(canvas => {
  })
}
      

完整代码

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
  install (Vue, options) {
    Vue.prototype.getPdfFromHtml = function (ele, pdfFileName, hide) {
      // this.$message.loading('正在下载', 2.5)
      ele = document.getElementById('pdfDom')
      pdfFileName = pdfFileName || 'pdf'
      window.pageYoffset = 0 // 滚动置顶
      document.documentElement.scrollTop = 0
      document.body.scrollTop = 0
      // ele.style.fontSize = '18px'
      // ele.style.padding='30px';
      // let scale = window.devicePixelRatio * 2
      html2Canvas(ele, {
        // dpi: 300,
        // dpi: window.devicePixelRatio * 4, // 将分辨率提高到特定的DPI 提高四倍
        // scale: 4, // 按比例增加分辨率
        // logging: false,
        // scale:scale,
        useCORS: true, // 允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
        // allowTaint: false,
        // height: ele.offsetHeight,
        // width: ele.offsetWidth,
        windowWidth: document.body.scrollWidth,
        windowHeight: document.body.scrollHeight
        // backgroundColor: '#fff'
      }).then(canvas => {
        // const _this = this
        // 未生成pdf的html页面高度
        var leftHeight = canvas.height
        var a4Width = 555.28 // 原A4宽 592 因为要设置边距 20 ,这里要减掉 40
        var a4Height = 801.89 // 原A4高   841 因为要设置边距 20 ,这里要减掉 40
        // 一页pdf显示html页面生成的canvas高度;
        var a4HeightRef = Math.floor(canvas.width / a4Width * a4Height)

        // pdf页面偏移
        var position = 0

        var pageData = canvas.toDataURL('image/jpeg', 1.0)

        var pdf = new JsPDF('x', 'pt', 'a4')
        // let printIndex = 1
        const canvas1 = document.createElement('canvas')
        let height
        pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen')

        function createImpl (canvas) {
          if (leftHeight > 0) {
            // printIndex++
            var checkCount = 0
            if (leftHeight > a4HeightRef) {
              var i = position + a4HeightRef
              for (i = position + a4HeightRef; i >= position; i--) {
                var isWrite = true
                for (var j = 0; j < canvas.width; j++) {
                  var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data

                  if (c[0] !== 0xff || c[1] !== 0xff || c[2] !== 0xff) {
                    isWrite = false
                    break
                  }
                }
                if (isWrite) {
                  checkCount++
                  if (checkCount >= 10) {
                    break
                  }
                } else {
                  checkCount = 0
                }
              }
              height = Math.round(i - position) || Math.min(leftHeight, a4HeightRef)
              if (height <= 0) {
                height = a4HeightRef
              }
            } else {
              height = leftHeight
            }

            canvas1.width = canvas.width
            canvas1.height = height

            // console.log(index, 'height:', height, 'pos', position);

            var ctx = canvas1.getContext('2d')
            ctx.drawImage(canvas, 0, position, canvas.width, height, 0, 0, canvas.width, height) // 边距这里设置0,不然又黑边

            // var pageHeight = Math.round(a4Width / canvas.width * height)
            // pdf.setPageSize(null, pageHeight)
            if (position !== 0) {
              pdf.addPage()
            }
            // 设置 20px 边距
            pdf.addImage(canvas1.toDataURL('image/jpeg', 1.0), 'JPEG', 20, 20, a4Width, a4Width / canvas1.width * height)
            leftHeight -= height
            position += height
            if (leftHeight > 0) {
              // 添加全屏水印
              /* const base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAArCAYAAADIWo5HAAACLUlEQVR42u2Zy2sCMRDGV9tbtVJKrQ/0JBWLvbgsaOttQQqreO5R6GHP/v+HZiEDQ9i8k33YDHyXbcxufpN8maRRFCJEiBAhQoTgRIfoh+hKNBe0G9I2GVG3om9bEl2I9rcIoE/77Cq8Myd6sn2ZSBgAr80YARhI+gOwCdGW6EB/d6R9XDUGFrsAf2Fe7Fswk1JBmzMd1DNKgI2EywQyUKYjkxFeOwwxkwgAvBJNqEa0DzaTHcn3qWrXdA/ocQD8m11ABUDfQF0fpujjI2QAeoZetdYdfOzB9HgGNEF6owM8Ec3Q8wEDgP07T6ktgNyB8YgAqGZ0b+gRsS2AtQP/iAUAHlAdsEW7TY6eFVrVNQN8A2AjlZho5R5wYjJhoqMiADy4DFWLPJMcKBhv3AYThFi4yJyrAAAfDrY/1SVQVhLDOWDowIwzSQ1TqwfA1P5CU3yJlsPY8fmjcTMgptmeIwB3aFbsLCvM2BRAFR4AZXYxuEdmn38hmjoosY0B5IonxLNhIYTNby0odMoAJJL1/k10bwpgQztZKaxb2YXFRnAUhexDHzoAUsGxu3j+awNA5+RmcxW1UCx1eQB4SyI1AaBrbiMEYGrwexgYBlgrgGtU/ZUY3AlGhgByTvV5MQGgW1SomqBOUWLiATy1wgNsABQz51PzWHxTALzWAW0F0EM+MKPmnLj6x0lbAPDuC5zfNPsCcChZ25DZd4VBJCW7wrRp1+whQoQIESJEg+IPRa38G55TPkQAAAAASUVORK5CYII='
              for (let i=0;i<6;i++) {
                for (let j=0;j<5;j++) {
                  const  left = (j * 120) + 20
                  pdf.addImage(base64,'JPEG', left, i*150, 20, 30); // 关掉水印
                }
              } */
              setTimeout(createImpl, 500, canvas)
            } else {
              pdf.save(pdfFileName + '.pdf')
              setTimeout(hide, 500)
              // this.$message.success('下载完成', 2.5)
            }
          }
        }

        // 当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < a4HeightRef) {
          pdf.addImage(pageData, 'JPEG', 20, 20, a4Width, a4Width / canvas.width * leftHeight)
          pdf.save(pdfFileName + '.pdf')
        } else {
          try {
            pdf.deletePage(0)
            setTimeout(createImpl, 500, canvas)
          } catch (err) {
            console.log(err)
          }
        }
      })
    }
  }
}


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值