Vue使用html2canvas和jspdf生成pdf文件

上篇刚写了html2canvas用法:使用html2canvas将页面或某个dom元素保存/下载为图片感兴趣可以去看下。

首先jspdf这个库就是用来生成pdf的,那为什么还需要使用到html2canvas。是因为jspdf直接生成pdf的话,用法可能会有些繁琐,并且可能不能保证原来的样式,不美观,也不满足需求。

所以我们先使用html2canvas将目标dom元素转为canvas,然后调用canvas的toDataURL方法将其转为base64编码,然后再将图片添加到pdf中就可以了。

1. 安装

pnpm add html2canvas
pnpm add jspdf

2. 引入  

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

3. 封装使用 

我这里将生成pdf方法单独封装在generatePdf.js文件中,向外导出这个方法拱外界使用 

generatePdf.js 

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

/**
 * 将指定的dom元素转为pdf 并下载
 * @param {element} dom 
 * @param {string} filename 
 */
export default function (dom, filename) {
  document.documentElement.scrollTop = 0
  document.body.scrollTop = 0
  html2Canvas(dom, {
    allowTaint: true,
    useCORS: true,
    // scale: 2,
    height: dom?.scrollHeight || 1080,
    windowHeight: dom?.scrollHeight || 1080
  }).then(canvas => {
    let contentWidth = canvas.width;
    let contentHeight = canvas.height;
    // 一页pdf显示html页面生成的canvas高度;
    let pageHeight = contentWidth * 841.89 / 592.28;
    // 未生成pdf的html页面高度
    let leftHeight = contentHeight;
    // 页面偏移
    let position = 0;
    // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
    let imgWidth = 595.28;
    let imgHeight = 592.28 / contentWidth * contentHeight;
    let pageData = canvas.toDataURL('image/jpeg', 1.0);
    let pdf = new JsPDF('', 'pt', 'a4');
    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();
        }
      }
    }
    /**
     * output可选参数
     * arraybuffer
     * blob
     * bloburi
     * datauristring
     * datauri
     * dataurlnewwindow
     * pdfobjectnewwindow
     * pdfjsnewwindow
     */
    // // 拿到生成的pdf的文件流 Blob二进制对象
    // const pdfBlob = pdf.output('blob')

    // 下载操作
    filename = filename.indexOf('.pdf') >= 0 ? filename : filename + '.pdf'
    pdf.save(filename);
  })
}

在使用的时候将要转为pdf的目标dom元素传入即可,第二个参数是当前转成pdf并下载的pdf文件名称 

下面贴一下测试页面完整代码 

<template>
  <div class="jspdf">
    <div class="toolbar">
      <button @click="toPdf">转为pdf</button>
    </div>
    <div class="pdf-container">
      <div class="chart-container">
        <Echart id="echart1" />
      </div>
      <div class="chart-container">
        <Echart id="echart2" />
      </div>
      <div class="chart-container">
        <Echart id="echart3" />
      </div>
      <div class="chart-container">
        <Echart id="echart4" />
      </div>
    </div>
  </div>
</template>
<script setup>
import Echart from './echart.vue'
import generatePdf from './generatePdf'

// 生成pdf
const toPdf = () => {
  generatePdf(document.querySelector('.pdf-container'), '图表')
}
</script>
<style scoped>
.jspdf {
  width: 100%;
  height: 100%;
  padding: 20px 0 0 20px;
  box-sizing: border-box;
  overflow-x: hidden;
}

.pdf-container {
  width: 600px;
  overflow: auto;
  overflow-x: hidden;
}

.chart-container {
  width: 100%;
  height: 500px;
  border: 1px dashed red;
  padding: 20px;
  box-sizing: border-box;
}

.toolbar {
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
}

button {
  padding: 8px 15px;
  box-sizing: border-box;
}
</style>

4. 效果: 

 

猜你喜欢

转载自blog.csdn.net/m0_51431448/article/details/130151355