html2canvas和jspdf导出pdf,每个页面模块占一页,在pdf中垂直居中显示

需求:html页面转换pdf,页面有多个模块,页面中有文本、echarts、表格等模块,一个模块占一页,因为模块高度不够,所以需要垂直居中
通过html2canvas和jspdf实现,html2canvas用于将页面元素生成canvas,jspdf用于将页面元素导出pdf
效果:html2canvas和jspdf导出pdf,每个页面模块占一页,在pdf中垂直居中显示_第1张图片
以下代码可以直接运行,背景图需要自行加一下
注意点:背景图片不支持跨域图片,非要使用跨域图片。可以通过js转成base64,使用base64设置背景图片
图片需要在服务器端才能正常导出,可以使用vscode的live-server插件

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="X-UA-Compatible"
      content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.1/echarts.min.js">script>
    <title>Documenttitle>
  head>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .module1,
    .module2 {
      background-image: url('../bg.jpg');
      background-repeat: no-repeat;
      background-size: 100% 100%;
      height: 100vh;
    }

    h1 {
      text-align: center;
      padding-top: 30vh;
      margin-bottom: 10vh;
      font-size: 100px;
      letter-spacing: 10px;
      font-weight: bold;
    }

    p {
      text-align: center;
      margin-top: 30px;
      font-size: 50px;
      font-weight: bold;
      letter-spacing: 10px;
    }

    button {
      display: block;
      margin: 0 auto;
      margin-top: 5vh;
      width: 20vh;
      height: 10vh;
      outline: none;
    }
    .module2 h1 {
      padding-top: 30px;
      font-size: 80px;
      margin-bottom: 40px;
    }

    .module2 p {
      margin-top: 10px;
      font-size: 40px;
    }

    .echarts {
      width: 100%;
      height: 70vh;
    }

    table {
      table-layout: fixed;
      word-break: break-all;
      width: 99%;
      margin: 0 auto;
    }
    table th {
      padding: 10px 20px;
      text-align: center;
    }
    table td {
      padding: 10px 20px;
      text-align: center;
    }

    .one {
      width: 300px;
    }
  style>

  <body>
    <div class="module1 module">
      <h1>你好世界h1>
      <p>2月3日p>
      <button onclick="downloadPDf()">下载pdfbutton>
    div>
    <div class="module2 module">
      <h1>echartsh1>
      <div class="echarts">div>
    div>
    <div class="module2 module">
      <h1>文本h1>
      <p>
        本网站上的图像不能用于以下目的。如有违反,将承担损害赔偿责任,敬请遵守。 1、不能用图像本身或处理过的图像的二次分发 2、不能用作服务标记或商标 3、不能使用违法、虚假、诽谤、侵权等违反公序良俗的内容。 4、不能用作色情图片 5、不能用于成人媒体、娱乐相关(包括歌舞俱乐部等)和约会服务
        6、不能用于互联网异性恋介绍业务 7、不能用在消费金融中的应用 8、不能欺骗,例如使用人的照片通过各种软件渠道去骗取任性与钱财 9、不能用照片损坏国家形象和利益
      p>
    div>
    <div class="module2 module">
      <h1>表格h1>
      <table
        border="1"
        cellspacing="0"
        cellpadding="0"
        border="1">
        <tr>
          <th class="one">故障统计th>
          <th>1月27日th>
          <th>1月28日th>
          <th>1月29日th>
          <th>1月30日th>
          <th>1月31日th>
          <th>2月1日th>
          <th>2月2日th>
          <th>周累计th>
        tr>
        <tr>
          <td class="one">风险td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
        tr>
        <tr>
          <td class="one">服务td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
          <td>0td>
        tr>
      table>
    div>
  body>
  <script>
    const myChart = echarts.init(document.querySelector('.echarts'))
    // 绘制图表
    myChart.setOption({
      xAxis: {
        data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
      },
      yAxis: {},
      series: [
        {
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    })
    const jsPDF = jspdf.jsPDF
    const downloadPDf = async dom => {
      // 对于一些不想显示在pdf上的元素,设置display:none,比如隐藏所有button
      const buttons = document.querySelectorAll('button')
      buttons.forEach(item => {
        item.style.display = 'none'
      })
      // 获取所有需要生成pdf的模块
      const modules = document.querySelectorAll('.module')
      if (!modules.length) return
      // a4纸固定宽高
      const a4Width = 595.28
      const a4Height = 841.89
      const pdf = new jsPDF('p', 'pt')
      // 生成所有pdf页
        async function setPdfPage() {
        for (let i = 0; i < modules.length; i++) {
          const item = modules[i]
          const canvas = await html2canvas(item)
          const contentWidth = canvas.width
          const contentHeight = canvas.height
          const pageData = canvas.toDataURL('image/jpeg', 1) // 第二个参数为图片质量,1为最高质量
          let imgHeight = (a4Width / contentWidth) * contentHeight // 根据a4纸比例,计算出图片的高度
          // 分页剩余高度
          let leftHeight = imgHeight
          // 分页偏移位置
          let position = 0
          // 如果图片高度大于a4纸高度,则需要分页
          if (imgHeight > a4Height) {
            while (leftHeight > 0) {
              // 第三个参数图片x轴位置,第四个参数图片y轴位置,第五个参数图片宽度,第六个参数图片高度
              pdf.addImage(pageData, 'JPEG', 0, position, a4Width, imgHeight)
              leftHeight = leftHeight - a4Height
              position -= a4Height
              if (leftHeight > 0) {
                pdf.addPage()
              }
            }
          } else {
            const marginY = (a4Height - imgHeight) / 2 // 计算出图片的上下边距
            // 第三个参数图片x轴位置,第四个参数图片y轴位置,第五个参数图片宽度,第六个参数图片高度
            pdf.addImage(pageData, 'JPEG', 0, marginY > 0 ? marginY : 0, a4Width, imgHeight)
          }
          // 最后一个模块不需要再新增空白页
          if (i < modules.length - 1) {
            pdf.addPage()
          }
        }
      }
      await setPdfPage()
      pdf.save('TestReport.pdf') // 导出pdf
      // 还原元素
      buttons.forEach(item => {
        item.style.display = 'block'
      })
    }
  script>
html>

你可能感兴趣的:(pdf,echarts,javascript)