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

news2024/12/27 1:56:15

需求:html页面转换pdf,页面有多个模块,页面中有文本、echarts、表格等模块,一个模块占一页,因为模块高度不够,所以需要垂直居中
通过html2canvas和jspdf实现,html2canvas用于将页面元素生成canvas,jspdf用于将页面元素导出pdf
效果:在这里插入图片描述
以下代码可以直接运行,背景图需要自行加一下
注意点:背景图片不支持跨域图片,非要使用跨域图片。可以通过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>Document</title>
  </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()">下载pdf</button>
    </div>
    <div class="module2 module">
      <h1>echarts</h1>
      <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>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
        </tr>
        <tr>
          <td class="one">服务</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
          <td>0</td>
        </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纸比例,计算出图片的高度
          const marginY = (a4Height - imgHeight) / 2 // 计算出图片的上下边距
          // 第三个参数图片x轴位置,第四个参数图片y轴位置,第五个参数图片宽度,第六个参数图片高度
          pdf.addImage(pageData, 'JPEG', 0, marginY > 0 ? marginY : 0, a4Width, imgHeight > a4Height ? a4Height : imgHeight)
          // 最后一个模块不需要再新增空白页
          if (i < modules.length - 1) {
            pdf.addPage()
          }
        }
      }
      await setPdfPage()
      pdf.save('TestReport.pdf') // 导出pdf
      // 还原元素
      buttons.forEach(item => {
        item.style.display = 'block'
      })
    }
  </script>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/401576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

以java编写员工管理系统(测试过 无问题)

一、系统结果的部分展示 二、题目以及相关要求 三、组成 1.该系统由 Employee 类 、commonEmployee类、Testemd类和managerEmployee类组成 2.Employee实现的代码 public class Employee {private String id;private String name;private String job;private int holiday…

弱监督参考图像分割:Learning From Box Annotations for Referring Image Segmentation论文阅读笔记

弱监督参考图像分割&#xff1a;Learning From Box Annotations for Referring Image Segmentation论文阅读笔记一、Abstract二、引言三、相关工作A、全监督参考图像分割B、基于 Box 的实例分割C、带有噪声标签的学习四、提出的方法A、概述B、伪标签生成目标轮廓预测Proposal 选…

exe打包工具:advanced installer介绍(一)

前言近年来&#xff0c;web服务逐渐走向云端部署浏览器化、去APP化&#xff0c;然而exe安装仍有着举足轻重的地位&#xff0c;其好处不言而喻&#xff0c;拿到exe安装包后&#xff0c;基本就可以傻瓜安装和操作了&#xff0c;十分便捷。业务场景通过各种IDE/QT/C#/Java等开发工…

项目的生命周期与成本、风险、变更的关系

成本与人力投入水平 项目成本的投入在初始阶段逐渐增加&#xff0c;在执行的中间阶段达到顶峰&#xff0c;在项目收尾阶段逐渐下降。成本的投入趋势如下图所示&#xff1a; 初始阶段&#xff1a;从人力成本来看&#xff0c;信息系统开发团队在前期制定项目管理章程及项目管理…

PCB焊盘设计基本原则

SMT的组装质量与PCB焊盘设计有直接的关系&#xff0c;焊盘的大小比例十分重要。如果PCB焊盘设计正确&#xff0c;贴装时少量的歪斜可以再次回流焊纠正(称为自定位或自校正效应)&#xff0c;相反&#xff0c;如果PCB焊盘设计不正确&#xff0c;即使贴装位置十分准确&#xff0c;…

图像金字塔,原理、实现及应用

什么是图像金字塔 图像金字塔是对图像的一种多尺度表达&#xff0c;将各个尺度的图像按照分辨率从小到大&#xff0c;依次从上到下排列&#xff0c;就会形成类似金字塔的结构&#xff0c;因此称为图像金字塔。 常见的图像金字塔有两类&#xff0c;一种是高斯金字塔&#xff0…

为什么越来越多的人开始学习大数据

因为根据国内的发展形势&#xff0c;大数据未来的发展前景会非常好&#xff0c;前景好需求高&#xff0c;自然会吸引越来越多的人进入大数据行业 我国市场环境处于急需大数据人才但人才不足的阶段&#xff0c;所以未来大数据领域会有很多的就业机遇。 2022年春季&#xff0c;…

camunda流程引擎基本使用(笔记)

文章目录一、camunda基础1.1 安装与部署流程引擎1.2 流程引擎结构1.3 流程引擎的基本使用1.3.1 创建一个BPMN Diagram1.3.2 实现一个外部工作者1.3.3 部署流程1.3.4 创建一个流程实例并消费1.3.5 向流程中添加用户任务1.3.6 添加网关1.3.7 业务规则二、Java 集成流程引擎2.1 为…

酷开科技大数据揭秘!酷开系统中的千屏千面究竟指的是什么?

互联网行业的快速发展&#xff0c;给我们带来了极大的便利。回顾整个互联网行业的发展历程&#xff0c;从PC时代到移动互联网时代&#xff0c;从移动互联网时代到物联网时代&#xff0c;现在又即将从物联网时代迈入人工智能时代。这些飞速发展的背后&#xff0c;其实是对数据利…

ICG-alkyne,吲哚菁绿-炔基结构式,实验室科研试剂,CAS号:1622335-41-4

ICG-alkyne,吲哚菁绿-炔基 中文名称&#xff1a;吲哚菁绿-炔基 CAS号&#xff1a;1622335-41-4 英文名称&#xff1a;ICG-alkyne 英文别名&#xff1a;ICG-alk 性状&#xff1a;绿色粉末 化学式&#xff1a;C48H53N3O4S 分子量&#xff1a;768.03 溶剂&#xff1a;溶于…

3BHE029110R0111 ABB

3BHE029110R0111 ABB变频器控制方式低压通用变频输出电压为380&#xff5e;650V&#xff0c;输出功率为0.75&#xff5e;400kW&#xff0c;工作频率为0&#xff5e;400Hz&#xff0c;它的主电路都采用交—直—交电路。其控制方式经历了以下四代。1U/fC的正弦脉宽调制&#xff0…

ggplot2的组图拓展包(1):patchwork(中篇)

专注系列化、高质量的R语言教程推文索引 | 联系小编 | 付费合集上篇和上篇续介绍了使用操作符进行组图的方法&#xff0c;这里默认读者已经能够理解各种操作符在本篇推文中的使用场景。本篇目录如下&#xff1a;0 示例图形6 plot_layout函数&#xff08;下&#xff09;6.1 guid…

CSS3-数据可视化

2D动画 - transform CSS3 transform属性允许你旋转&#xff0c;缩放&#xff0c;倾斜或平移给定元素。 Transform是形变的意思&#xff08;通常也叫变换&#xff09;&#xff0c;transformer就是变形金刚 常见的函数transform function有&#xff1a; 平移&#xff1a;transl…

实际开发中如何存储密码(md5加盐bcrypt)golang

文章目录简介加盐的加密方式md5 加盐方式bcrypt 方式简介 一般前端把用户密码发给服务端&#xff0c;服务端实际业务中如何存储密码呢&#xff0c;如何存储密码才能保证密码不被开发者获取或者被截取呢&#xff0c;保证密码的安全 加盐的加密方式 现在的企业开发大都采用这种…

凌恩生物文献分享|颠覆性的宏基因组新思路,速来get!

非人灵长类动物&#xff08;NHP&#xff09;是人类的近亲&#xff0c;为宿主-微生物互作的研究提供了一个很好的例子。近年来研究主要集中在野生灵长类动物的肠道微生物群&#xff0c;这将有助于了解灵长类及其肠道微生物群的进化&#xff0c;但仍然缺乏关于野生种群肠道微生物…

通用后台管理系统-前端搭建

一 背景 基于vuespringboot 搭建一套通用管理后台 主要包括用户管理模块、权限模块、菜单模块 二 环境信息 2.1 前端工具版本 2.1.1 npm 版本 PS D:\front> npm -v 8.5.0PS D:\front> npm config get registry https://registry.npm.taobao.org/ PS D:\front>2.1…

埋点tracker:前端埋点服务-技术要点梳理

一、背景埋点方案&#xff0c;前端涉及到哪些技术要点&#xff0c;本文做简单的梳理和总结。二、指纹追踪技术&#xff1a;识别到用户及设备浏览器&#xff1a;浏览器指纹_snowli的博客-CSDN博客三、用户设备信息&#xff08;navigator&#xff09;navigator.userAgent四、页面…

利用Mysql存储过程造百万级数据

1.准备工作&#xff08;1&#xff09;由于是使用存储过程&#xff0c;mysql从5.0版开始支持存储过程&#xff0c;那么需要mysql的版本在5.0或者以上。如何查看mysql的版本&#xff0c;使用下面sql语句查看&#xff1a;&#xff08;2&#xff09;创建两张表&#xff0c;表结构一…

Android Crash和ANR监控

文章目录一、Crash1.1 概念1.2 类型二、ANR2.1 概念2.2 类型2.2.1 KeyDispatchTimeout&#xff08;常见&#xff09;2.2.2 BroadcastTimeout2.2.3 ServiceTimeout2.2.4 ContentProviderTimeout三、测试中如何关注3.1 Crash测试关注方法3.2 ANR测试关注方法四、如何记录与处理4.…

C++复习笔记--STL的string容器和vector容器

1--string容器string 本质上是一个类&#xff0c;其不同于指针 char*&#xff0c;string 类的内部封装了 char*&#xff0c;用于管理字符串&#xff0c;是一个 char* 型的容器&#xff1b;1-1--string构造函数string 的构造函数原型&#xff1a;string(); // 创建一个空的字符串…