在uni中使用vue3写h5的pdf导出

先安装依赖

npm install --save html2canvas
npm install jspdf --save

把dom转canvas,屏幕截图基于 DOM,因此可能不是 100% 准确到真实表示,因为它不会制作实际的屏幕截图,而是根据页面上可用的信息构建屏幕截图。

components/pdf  创建pdf文件夹


import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'export default {install: (Vue, options) => {/*** targetDom: 需要打印的dom对象* name:pdf的名字* callback: 回调函数*/Vue.config.globalProperties.$createPdf = (targetDom, name, callback) => {console.log(window.devicePixelRatio * 4)// a4纸的尺寸[592.28,841.89]uni.showLoading({title: '导出中'})const A4_WIDTH = 592.28const A4_HEIGHT = 841.89// 每页pdf 相对于A4纸张的页面所对应的高度let pageHeight = targetDom.scrollWidth / A4_WIDTH * A4_HEIGHT//将dom对象复制一份出来,我们要对dom对象的大小进行调整,不能影响原页面dom对象的样式let cloneDom = targetDom.cloneNode(true)cloneDom.style.width = targetDom.scrollWidth + 'px'cloneDom.style.background = '#FFFFFF'// cloneDom.style.display = 'none'document.body.appendChild(cloneDom)//这里划重点,将页面中的预计生成一页的div设置一个单独的class,然后根据class获取到所有的节点,即可大致知道将要生成多少页的PDFlet pages = cloneDom.childNodes//遍历一次这些节点for (let i = 0; i < pages.length; i++) {//判断每个页面的节点对象,高度是否大于或小于实际的PDF的高度,如果大于PDF每页的高度,那这个节点最少也要生成2页的PDF,切不能影响下面的节点的,用节点对象的高度/PDF每页的高度,向上取整获取到倍数,然后设置该节点的高度为:PDF每页的高度*倍数,如果节点高度小于PDF每页的高度,直接将该节点高度设置成PDF每页的高度即可if (pages[i].offsetHeight > pageHeight) {// let num = Math.ceil(pages[i].offsetHeight / pageHeight)console.log(pages[i].style,'*-*-*-')// pages[i].style.height = pageHeight * num + 'px'} else {// pages[i].style.height = pageHeight + 'px'}//页面中每页的div之间有间隔,将这个间隔去掉// pages[i].style.marginBottom = 0 + 'px'}html2canvas(cloneDom, {scale: 4, // 提升画面质量,但是会增加文件大小useCORS: true, // 允许跨域图片 当图片是链接地址时,需加该属性,否组无法显示图片imageTimeout: 0, // 图片加载延迟,默认延迟为0,单位毫秒height: cloneDom.scrollHeight, // canvas的高度设定,这里的宽高要用复制出来的dom对象的宽高,不能用原dom对象,因为我们已经将dom的高度整体拉高了width: cloneDom.scrollWidth, // canvas的宽度设定windowWidth: document.body.scrollWidth,windowHeight: document.body.scrollHeight,dpi: 172, // 将分辨率提高到特定的DPIlogging: false,allowTaint: false,}).then(canvas => {document.body.removeChild(cloneDom) // 移除节点否者会多出一份const _this = this;//未生成pdf的html页面高度var leftHeight = canvas.height;var a4Width = 555.28 // 原A4宽 592 因为要设置边距 20 ,这里要减掉 40var 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');var index = 1,canvas1 = document.createElement('canvas'),height;pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen');function createImpl(canvas) {if (leftHeight > 0) {index++;var checkCount = 0;if (leftHeight > a4HeightRef) {var i = position + a4HeightRef;for (i = position + a4HeightRef; i >= position; i--) {var isWrite = truefor (var j = 0; j < canvas.width; j++) {var c = canvas.getContext('2d').getImageData(j, i, 1, 1).dataif (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {isWrite = falsebreak}}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;// $('.pdfProgress').text(index + 1);// $('.pdfTotal').text(index + Math.ceil(leftHeight / a4HeightRef));if (leftHeight > 0) {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('下载pdf文件名' + '.pdf');uni.hideLoading()}}}//当内容未超过pdf一页显示的范围,无需分页if (leftHeight < a4HeightRef) {pdf.addImage(pageData, 'JPEG', 20, 20, a4Width, a4Width / canvas.width * leftHeight);pdf.save('下载pdf文件名' + '.pdf')uni.hideLoading()} else {try {pdf.deletePage(0);setTimeout(createImpl, 500, canvas);} catch (err) {console.log(err);}}})}}
}

在main文件中引入

import htmlToPdf from '@/components/pdf/pdf.js'app.use(htmlToPdf);

在需要的页面绑定id  事件

	import {getCurrentInstance} from 'vue';const {appContext} = getCurrentInstance();// 下载报告const down = () => {let target = document.querySelector('#targetDom'); //ID获取节点对象appContext.config.globalProperties.$createPdf(target, '报告');
}

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

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

相关文章

linux 一键安装docker docker-compose

# 环境 deploy.sh docker-19.03.9.tgz docker-compose-linux-x86_64 tar -zxvf docker-19.03.9.tgz mv docker-19.03.9 docker cp docker/* /usr/bin/ touch /etc/systemd/system/docker.service cat << EOG > /etc/systemd/system/docker.service [Unit] Descripti…

【技巧】Maven重复依赖分析查找

【技巧】Maven重复依赖分析查找 遇到奇葩的错误可以考虑是不是依赖冲突了 比如同一段代码 再这个项目中好好的 另一个项目中不能用等 idea安装插件 maven helper 打开pom文件 输入要查找的依赖 将不用的排除掉 右键排除即可

“深入解析API接口:原理、用途和最佳实践“

API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;是不同软件或系统之间进行交互的桥梁&#xff0c;它提供了一组定义好的规则和功能&#xff0c;使得不同的应用程序能够相互通信和交换数据。API接口的理解、应用和最佳实践对于开发者…

在阿里云平台注册一个域名

我们访问阿里云官网 阿里云 然后 我们右上角点击登录 然后 按正常操作流程登录 登录成功后 我们点击控制台 我们将鼠标 移入 右上角 图片指向的位置 我们点击域名 进入界面后点击注册域名 在输入框中输入域名内容 然后 按回车 然后弹出的列表 我们可以选一个未注册的 点击…

解决Linux打开文件数过多error:too many open files

解决Linux打开文件数过多error:too many open files #查看当前的最大打开文件数 ulimit -n #默认只有1024,当负载较大的服务器时&#xff0c;很容易遇到error: too many open files。因此&#xff0c;需要将其改大。#可临时修改&#xff0c;但重启后就无效 ulimit -n 65535 #查…

Druid-排查conditionDoubleConstAllow配置问题(double const condition)

Druid-排查conditionDoubleConstAllow配置问题(double const condition) 报错信息 Caused by: java.sql.SQLException: sql injection violation, dbType postgresql, druid-version 1.2.18, double const condition : SELECT * FROM test where 11 AND TRUE AND TRUE关键词&…

正则表达式概念以及语法的使用

目录 1.概念 2. 为什么使用正则表达式&#xff1f; 3. 语法 1.普通字符 非打印字符 2. 特殊字符 3. 限定符 4. 定位符 5. 运算优先级 3.匹配规则 1. 基本模式匹配 2. 字符簇 3. 确定重复出现 1.概念 正则表达式(Regular Expression)是一种文本模式&#xff0c;包…

【Docker】docker-compose基本使用

【Docker】docker-compose基本使用 文章目录 【Docker】docker-compose基本使用1. docker 项目部署弊端2. docker-compose 简介3. 实践4. 模板命令4.1 build 指令4.2 command 指令4.3 container_name 指令4.4 depends_on 指令4.5 env_file 指令4.6 environment 指令4.7 image 指…

基于Redisson的Redis分布式锁

Redisson分布式锁_redissonclient_甩锅虾的博客-CSDN博客 *** 分布式锁*/ public interface DistributedLock {/*** 尝试获取锁* param lockName* param seconds* return*/Boolean tryAcquire(String lockName, long seconds, TimeUnit unit);/*** 释放锁* param lockKey*/v…

如何使用自动化构造随机路由模型

为什么要仿真随机路由&#xff1f; 路由器测试中&#xff0c;为了最大程度还原现网路由情况&#xff0c;评估路由器在现网环境下稳定工作各项指标&#xff0c;需要对导入路由进行离散仿真&#xff0c;目前路由仿真可分为导入路由与生成路由两种方式&#xff0c;导入路由需要现…

vue如何使用webscorket实现多人协同在线表格填写

要使用WebSocket在Vue中实现多人协同在线表格填写&#xff0c;你可以按照以下步骤进行操作&#xff1a;1. 安装WebSocket库&#xff1a;首先&#xff0c;在Vue项目中安装WebSocket库。你可以使用 socket.io-client 库来处理WebSocket通信。使用npm或yarn安装它&#xff1a;npm …

学习遇上的一点补救

从开始学习java到现在逐步确定好发展路线。是时候停一下步伐了。 之前不停的往前走&#xff0c;从学校的课程、书本开始&#xff0c;没有借助网课、视频&#xff0c;依靠自己一步一个脚印。从Java实用程序、Javaweb、JavaEE然后选择MySQL数据库、然后觉得有必要对前端了解&…

think-on-graph: 基于知识图谱的大模型推理

概述 本文的研究背景是大规模语言模型在复杂推理任务中存在困难并展示了较低的性能&#xff0c;特别是在需要知识的追溯能力、及时性和准确性的场景中。 过去的方法主要面临两个问题&#xff1a;推理不负责任容易生成虚构或带有有害文本&#xff0c;以及模型在预训练阶段无法…

【深入浅出C#】章节 5: 高级面向对象编程:泛型编程和集合类型

高级面向对象编程是在基础面向对象编程的基础上进一步深入和拓展的一种编程范式。它强调封装、继承和多态的概念&#xff0c;并引入了泛型编程和集合类型等高级特性。高级面向对象编程提供了更灵活、可扩展和可复用的代码结构&#xff0c;能够帮助开发者构建更复杂、更高效的应…

基于IPC-CFX的点对点通信C#

IPC-CFX有两种主要的通信方式&#xff0c;可以通过RabbitMQ发布和订阅&#xff0c;也可以通过request和response进行点对点的通信&#xff0c;本文主要讲的是点对点的通信方式。 在vscode里建立新的dotnet项目&#xff0c;可以通过终端输入dotnet new console来建立&#xff0c…

【拿来就能用】C#指定打印机打印的类

之前写过一个“C#WinForm程序中选择打印机打印”的文章&#xff0c;但在使用过程中&#xff0c;尤其是生成Word文档时&#xff0c;会感觉系统响应较慢。如果不需要留存打印文档的电子版&#xff0c;可以使用下面的类直接打印。相比之前的方法&#xff0c;这种方法更简单&#x…

MySQL常用语句大全

语句 DDL MySQL的DDL&#xff08;数据定义语言&#xff09;是一组用于创建、修改和删除数据库、表、索引、视图、存储过程和触发器等数据库对象的语句。下面是一些常用的MySQL DDL语句和它们的详细说明&#xff1a; alter 在MySQL中&#xff0c;DDL&#xff08;数据定义语言…

LCD—STM32液晶显示(2.使用FSMC模拟8080时序)

目录 使用STM32的FSMC模拟8080接口时序 FSMC简介 FSMC NOR/PSRAM中的模式B时序图 用FSMC模拟8080时序 重点&#xff1a;HADDR内部地址与FSMC地址信号线的转换&#xff08;实现地址对齐&#xff09; 使用STM32的FSMC模拟8080接口时序 ILI9341的8080通讯接口时序可以由STM32使…

北邮国院物联网 Microprocessor 微处理器笔记

Introduction-随便聊 嵌入式系统是什么&#xff1f;专用的计算机系统。为专门功能可能对计算机架构&#xff0c;外设等做出一些取舍。 通常的限制&#xff1a;Cost&#xff08;比如大量部署传感器节点&#xff09;&#xff0c;Size and weight limits&#xff08;特定应用场景…

配置Hadoop_0

配置Hadoop_0 1配置Hadoop100模板虚拟机1.1配置Hadoop100模板虚拟机硬件1.2配置Hadoop100模板虚拟机软件1.3配置Hadoop100模板虚拟机IP地址1.4配置Hadoop100模板虚拟机主机名称/主机名称映射1.5配置Hadoop100模板虚拟机远程操作工具 1配置Hadoop100模板虚拟机 Hadoop100 内存…