Vue 实现页面导出A4标准大小的PDF文件,以及处理图片跨域不能正常展示的问题等

效果预览:

代码流程:首先在utils文件夹下创建htmlToPdf的js工具文件,然后在main.js中注册引用

htmlToPdf.js

// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

export default {
  install(Vue, options) {
    Vue.prototype.getPdf = function (id) {
      var title = '导出试卷'
      if (id === null || id === undefined) {
        id = '#pdfDom'
      }
      html2Canvas(document.querySelector(id), {
        allowTaint: true,
      }).then(function (canvas) {
        const contentWidth = canvas.width
        const contentHeight = canvas.height
        const pageData = canvas.toDataURL('image/jpeg', 1.0)
        const pdfX = contentWidth
        const pdfY = contentHeight // 500为底部留白
        const imgX = contentWidth
        const imgY = contentHeight // 内容图片这里不需要留白的距离
        const PDF = new JsPDF('', 'pt', [pdfX, pdfY])
        PDF.addImage(pageData, 'jpeg', 0, 0, imgX, imgY)
        PDF.save(title + '.pdf')
      })
    }

    Vue.prototype.getPdfByIds = function (pages) {
      var title = '导出试卷'
      let params = []
      let PDF = null

      let imgs = document.querySelectorAll('img')
      for (let img of imgs) {
        img.setAttribute('crossorigin', '*')
      }
      let parentNode = document.querySelector(pages)
      let promises = []
      for (let i = 0; i < parentNode.childNodes.length; i++) {
        let promise = new Promise((res, rej) => {
          let pageIndex = i
          html2Canvas(
            document.querySelector('#' + parentNode.childNodes[i].id),
            {
              allowTaint: true,
              // useCORS: true,
            }
          )
            .then(function (canvas) {
              const contentWidth = canvas.width
              const contentHeight = canvas.height
              let pageData = canvas.toDataURL('image/jpeg', 1.0)
              let pdfWidth = contentWidth
              let pdfHeight = contentHeight // 500为底部留白
              let imgX = contentWidth
              let imgY = contentHeight // 内容图片这里不需要留白的距离

              params.push({
                pageIndex: pageIndex,
                pageData: pageData,
                pdfWidth: pdfWidth,
                pdfHeight: pdfHeight,
              })

              res(PDF)
            })
            .catch((e) => {
              console.log('报错', e)
            })
        })
        promises.push(promise)
      }
      Promise.all(promises).then((val) => {
        params.sort(function (a, b) {
          let index1 = a['pageIndex']
          let index2 = b['pageIndex']
          return index1 - index2 //正序
        })
        let i = 0
        for (let param of params) {
          i++
          console.log('param', param)
          let pdfWidth = param['pdfWidth']
          let pdfHeight = param['pdfHeight']
          let pageData = param['pageData']

          if (PDF === null) {
            PDF = new JsPDF('', 'pt', [pdfWidth, pdfHeight])
          } else {
            PDF.addPage()
          }
          PDF.addImage(pageData, 'jpeg', 0, 0, pdfWidth, pdfHeight)
        }
        if (params.length == parentNode.childNodes.length) {
          PDF.save(title + '.pdf')
        }
      })
    }

    Vue.prototype.getPdfByIdsB = function (pages) {
      var title = '导出试卷'
      let params = []
      let PDF = null

      let imgs = document.querySelectorAll('img')
      for (let img of imgs) {
        img.setAttribute('crossorigin', '*')
      }
      let parentNode = document.querySelector(pages)
      let promises = []
      for (let i = 0; i < parentNode.childNodes.length; i++) {
        let promise = new Promise((res, rej) => {
          let pageIndex = i
          html2Canvas(
            document.querySelector('#' + parentNode.childNodes[i].id),
            {
              allowTaint: true,
              useCORS: true,
            }
          )
            .then(function (canvas) {
              const contentWidth = canvas.width
              const contentHeight = canvas.height
              let pageData = canvas.toDataURL('image/jpeg', 1.0)
              let pdfWidth = contentWidth
              let pdfHeight = contentHeight // 500为底部留白
              let imgX = contentWidth
              let imgY = contentHeight // 内容图片这里不需要留白的距离
              params.push({
                pageIndex: pageIndex,
                pageData: pageData,
                pdfWidth: pdfWidth,
                pdfHeight: pdfHeight,
              })

              res(PDF)
            })
            .catch((e) => {
              console.log('报错', e)
            })
        })
        promises.push(promise)
      }
      Promise.all(promises).then((val) => {
        params.sort(function (a, b) {
          let index1 = a['pageIndex']
          let index2 = b['pageIndex']
          return index1 - index2 //正序
        })
        let i = 0
        for (let param of params) {
          i++
          console.log('param', param)
          let pdfWidth = param['pdfWidth']
          let pdfHeight = param['pdfHeight']
          let pageData = param['pageData']

          if (PDF === null) {
            PDF = new JsPDF('', 'pt', [pdfWidth, pdfHeight])
          } else {
            PDF.addPage()
          }
          PDF.addImage(pageData, 'jpeg', 0, 0, pdfWidth, pdfHeight)
        }
        if (params.length == parentNode.childNodes.length) {
          PDF.save(title + '.pdf')
        }
      })
    }
  },
}

在main.js中注册引用,挂载全局即可使用

import htmlToPdf from './utils/htmlToPdf'
Vue.use(htmlToPdf)

下载方法中,使用即可,#app为最外层父级元素id名称

//下载
      downloadPapaers() {
        Vue.prototype.getPdfByIdsB('#app')
      },
相关推荐
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic2 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
清灵xmf3 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据4 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161774 小时前
防抖函数--应用场景及示例
前端·javascript
334554324 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test4 小时前
js下载excel示例demo
前端·javascript·excel
PleaSure乐事4 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro