vue中使用html2canvas配合jspdf导出pdf(以及在导出时遇到的导出样式问题)

指定页面中导出为pdf格式并打包,使用html2canvas先转为图片格式,在利用jspdf转为pdf,最后下载打包为本地压缩包

yarn add html2canvas
yarn add jspdf
1. 注册一个插件并挂载
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {install(Vue, options) {Vue.prototype.getPdf = function (dom) {return new Promise((resolve, reject) => {html2Canvas(dom.$el, {allowTaint: true,scale: 2,dpi: 300,}).then(function (canvas) {let contentWidth = canvas.width;let contentHeight = canvas.height;let pdfWidth = 595.28; // A4 width in pixelslet pdfHeight = (pdfWidth / contentWidth) * contentHeight;let pageData = canvas.toDataURL('image/jpeg', 1.0);let PDF = new JsPDF('p', 'pt', 'a4');let scale = pdfWidth / contentWidth;PDF.addImage(pageData, 'JPEG', 0, 0, pdfWidth, pdfHeight);let remainingHeight = pdfHeight;while (remainingHeight < contentHeight) {PDF.addPage();let offsetY = -remainingHeight * scale;PDF.addImage(pageData, 'JPEG', 0, offsetY, pdfWidth, pdfHeight);remainingHeight += pdfHeight;}PDF.save('export.pdf'); //直接下载// resolve(PDF.output('blob')); //转为blob格式 返回合并下载}).catch(reject);});};}
}
2. 页面使用
DownPDFAndFile(){this.getPdf('传入ref或者是id')
}

以上正常导出步骤 封装方法 使用 但是如果你的项目中用的是rem布局或者是适配方法,样式或者字体没有显示出来被盖掉请往下看

3.由于在项目中用rem做了适配导致样式变形

在这里插入图片描述

4. 我们可以在html2canvas生成图片时把对应的样式或者添加类名,在生成图片前修改样式,转换为pdf后恢复初始样式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
/*** @param {*} 添加样式类名*/
function removeChildrenWithClass(parent, className) {var children = parent.childNodes;if (parent.classList && parent.classList.contains('form_view_item')) {parent.childNodes.forEach((item) => {item.className += ' is_to_print'})}for (var i = 0; i < children.length; i++) {if (children[i].classList && children[i].classList.contains('isprint')) {children[i].style.display = 'block'if (children[i].classList.contains('is_toprint')) children[i].style.display = 'block'}if (children[i].classList && children[i].classList.contains('form_view_title')) {children[i].style.marginTop = '25px'}if (children[i].classList && children[i].classList.contains(className)) {children[i].style.display = 'none'} else if (children[i].childNodes) {removeChildrenWithClass(children[i], className);}}
}
/*** @param {*} 恢复初始样式*/
function restoreOriginalState(parent, className) {var children = parent.childNodes;if (parent.classList && parent.classList.contains('form_view_item')) {parent.childNodes.forEach((item) => {item.classList.remove('is_to_print');});}for (var i = 0; i < children.length; i++) {if (children[i].classList && children[i].classList.contains(className)) {children[i].style.display = '';}if (children[i].classList && children[i].classList.contains('form_view_title')) {children[i].style.marginTop = '';}if (children[i].classList && children[i].classList.contains('isprint')) {children[i].style.display = 'none';}if (children[i].childNodes) {restoreOriginalState(children[i], className);}}
}
export default {install(Vue, options) {Vue.prototype.getPdf = function (dom) {return new Promise((resolve, reject) => {removeChildrenWithClass(dom.$el, 'noprint');html2Canvas(dom.$el, {allowTaint: true,//如果不要求清晰度可以去掉scale: 2,  //按比例增加分辨率 dpi: 300, //将分辨率提高到特定的 DPI}).then(function (canvas) {restoreOriginalState(dom.$el, 'noprint')let contentWidth = canvas.width;let contentHeight = canvas.height;let pdfWidth = 595.28; // A4 width in pixelslet pdfHeight = (pdfWidth / contentWidth) * contentHeight;let pageData = canvas.toDataURL('image/jpeg', 1.0);let PDF = new JsPDF('p', 'pt', 'a4');let scale = pdfWidth / contentWidth;PDF.addImage(pageData, 'JPEG', 0, 0, pdfWidth, pdfHeight);let remainingHeight = pdfHeight;while (remainingHeight < contentHeight) {PDF.addPage();let offsetY = -remainingHeight * scale;PDF.addImage(pageData, 'JPEG', 0, offsetY, pdfWidth, pdfHeight);remainingHeight += pdfHeight;}PDF.save('export.pdf'); //直接下载// resolve(PDF.output('blob')); //转为blob格式 返回合并下载}).catch(reject);});};}
}
5. 修改完后导出正常

在这里插入图片描述

6. 如果需求是直接下载以下就忽略,如果需求是打包为本地压缩包请继续
// 引入使用attachDownload方法
// 下载事件
async DownPDFAndFile() {const pdfinfo = await this.getPdf('传入ref或者是id')const pdfList = [//参数字段自行修改 为attachDownload 中的字段对应{id: "...",data: pdfinfo,},];const ImageList = []const VideoList = []const ImageAndVideoAndPdfList = [...pdfList,...ImageList,...VideoList]const { downloadStatus } = await this.is_downFile(ImageAndVideoAndPdfList);// downloadStatus 这个状态为下载状态 true为完成 可以自行添加业务},
// 下载方法
async is_downFile(list) {if (list.length > 0) {const config = {downloadList: list,suffix: "病历编辑.zip",};const { downloadStatus } = await attachDownload(config);return { downloadStatus };}},
7. 打包下载使用的是JSZip 和 FileSaver
yarn add jszip
yarn add file-saver
// attachDownload.js
import JSZip from "jszip";
import FileSaver from "file-saver";
export async function attachDownload(config) {const { downloadList, suffix } = configconst zip = new JSZip();const cache = {};let downloadStatus = falseconst downloadPromises = downloadList.map(async (item) => {try {if (item.url) {let data;if(item.type=='.pdf'){data = item.data;}else{data = await getImgArrayBuffer(item.url);}zip.folder(suffix).file(`${item.Title}_${item.FileID}` + item.type, data, { binary: true });cache[item.id] = data;} else {throw new Error(`文件${item.fileName}地址错误,下载失败`);}} catch (error) {console.error("文件获取失败", error);}});try {await Promise.all(downloadPromises);const content = await zip.generateAsync({ type: "blob" });FileSaver.saveAs(content, suffix);downloadStatus = truereturn {downloadStatus}} catch (error) {console.error("文件压缩失败", error);}
}
async function getImgArrayBuffer(url) {const response = await fetch(url);if (!response.ok) {throw new Error(`请求失败: ${response.status}`);}return await response.blob();
}

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

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

相关文章

记一次生产系统每隔10小时(36000000毫秒)固定进行一次Full GC排查思路

一、 背景描述 某个应用在生产环境通过系统监控发现&#xff0c;应用每隔10小时就会触发一次Full GC&#xff0c;该系统当时承接的业务量并不大&#xff0c;而且固定10小时就会进行Full GC&#xff0c;通过监控时间轴发现Full GC频率很规律&#xff0c;直觉告诉我这不是JVM自身…

寒假 day1

1、请简述栈区和堆区的区别? 2、有一个整形数组:int arr[](数组的值由外部输入决定)&#xff0c;一个整型变量: x(也 由外部输入决定)。要求: 1)删除数组中与x的值相等的元素 2)不得创建新的数组 3)最多只允许使用单层循环 4)无需考虑超出新数组长度后面的元素&#xff0c;所以…

【lesson40】理解文件系统

文章目录 问题磁盘结构&#xff08;物理&#xff09;磁盘的存储结构磁盘的抽象结构 问题 1.有没有没有被打开的文件&#xff1f;当然有 在哪里呢&#xff1f;磁盘中也叫磁盘级文件 2.学习磁盘级别文件的侧重点在哪&#xff1f; 站在单个文件角度: 这个文件在哪里&#xff1f…

【Linux】权限管理

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一 、Linux中的用户1.1 Linux用户分类1.2 用户转换1.3 指令提权 二、Linux权限管…

企业网络采用SD-WAN的优势

近年来&#xff0c;SD-WAN成为企业网络领域的一项热门技术&#xff0c;为传统网络带来了新的变革。SD-WAN&#xff08;Software Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;以其灵活性、可管理性和低成本而备受青睐。它不仅能够创建成熟的专用网络&#…

MySQL 教程 2.3

MySQL DELETE 语句 你可以使用 DELETE FROM 命令来删除 MySQL 数据表中的记录。 你可以在 mysql> 命令提示符或 PHP 脚本中执行该命令。 语法 以下是 DELETE 语句从 MySQL 数据表中删除数据的通用语法&#xff1a; DELETE FROM table_name WHERE condition; 参数说明&…

IP风险画像在企业网络安全中应用

随着企业数字化的不断深入&#xff0c;网络安全问题日益突显。IP风险画像作为一种综合性的网络安全工具&#xff0c;为企业提供了更全面的风险评估和防范手段。本文将结合一个实际案例&#xff0c;深入探讨IP风险画像在企业网络安全中的成功应用。 案例背景 一家大型金融机构…

IP数据云识别真实IP与虚假流量案例

随着互联网的普及&#xff0c;企业在数字领域面临着越来越复杂的网络威胁。为了保护网站免受虚假流量和恶意攻击的影响&#xff0c;许多企业正在采用IP数据云。本文将结合一个真实案例&#xff0c;深入探讨IP数据云如何成功准确地识别真实用户IP和虚假流量IP&#xff0c;提高网…

Oracle 面试题 | 09.精选Oracle高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

vue3 之 组合式API—reactive和ref函数

ref&#xff08;&#xff09; 作用&#xff1a;接收简单类型或者对象类型的数据传入并返回一个响应式的对象 核心步骤&#xff1a; 1️⃣ 从 vue 包中导入 ref 函数 2️⃣在 <script setup>// 导入import { ref } from vue// 执行函数 传入参数 变量接收const count …

【Python】【完整代码】解析Excel 文件中的内容并检查是否包含某字符串,并返回判断结果

示例&#xff1a; 开发需求&#xff1a;解析Excel 文件中的内容并检查是否包含 "Fail" 字符&#xff0c;若没有则返回True&#xff0c;若有则返回False 实现代码&#xff1a; #!/usr/bin/env python3 # -*- encoding: utf-8 -*-File : check_excel_for_fail.py Ti…

vue介绍和使用

一、vue介绍 vue官网说&#xff1a;Vue.js&#xff08;读音 /vjuː/&#xff0c;类似于 view&#xff09; 是一套构建用户界面的渐进式的JavaScript框架。与其他重量级框架不同的是&#xff0c;Vue 采用自底向上增量开发的设计。 1、渐进式的JavaScript框架 复制代码 Angular…

OJ_找位置

题干 代码 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<vector> #include<algorithm> #include<map> using namespace std;int main() {char str[200] { 0 };scanf("%s", str);map<char, vector<int>> times…

openlayers加载天地图

申请天地图key 官方&#xff1a;https://www.tianditu.gov.cn/ 申请key&#xff1a;https://sso.tianditu.gov.cn/login?servicehttps%3A%2F%2Fconsole.tianditu.gov.cn%2F 进去之后&#xff0c;先登录&#xff0c;如果没账号先注册一个就行。 可以创建个应用&#xff0c;…

如何将图片提取文字转换成文字?3个方法帮你转换

如何将图片提取文字转换成文字&#xff1f;在日常生活中&#xff0c;将图片中的文字转换成可编辑的文本可以带来很多便利。例如&#xff0c;我们可以使用OCR技术将书籍或报纸上的文章转换成电子文本&#xff0c;方便阅读和编辑。此外&#xff0c;将名片、菜单、广告等物品上的文…

政安晨的AI笔记——Bard大模型最新提示词创作绘画分析

AI大模型进入商业应用元年后的第一年&#xff0c;顶级模型大混战终于开始了。 Bard在追赶OpenAI的过程中&#xff0c;还是补上了画图的短板。 &#xff08;相比于视频的5阶张量处理而言&#xff0c;图画做为4阶张量处理虽然不新鲜&#xff0c;但却是跨不过去的基础条件&#…

LLM(5) | Encoder 和 Decoder 架构

LLM(5) | Encoder 和 Decoder 架构 文章目录 LLM(5) | Encoder 和 Decoder 架构0. 目的1. 概要2. encoder 和 decoder 风格的 transformer (Encoder- And Decoder-Style Transformers)原始的 transformer (The original transformer)编码器 (Encoders)解码器 (Decoders)编码器和…

【退役之重学前端】vite, vue3, vue-router, vuex, ES6学习日记

学习使用vitevue3的所遇问题总结&#xff08;2024年2月1日&#xff09; 组件中使用<script>标签忘记加 setup 这会导致Navbar 没有暴露出来&#xff0c;导致使用不了&#xff0c;出现以下报错 这是因为&#xff0c;如果不用setup&#xff0c;就得使用 export default…

一种缩短轮询时间的处理办法

我们平常处理轮询任务的时候&#xff0c;会用时间片的方式来分割开&#xff0c;每个时间片处理某一个任务。 有时候有些任务并不需要有动作&#xff0c;本轮轮询到它&#xff0c;它不需要干活&#xff0c;于是这个时间片就浪费了。但如果其他时间片里面的任务又急着呢&#xff…

新版本nginx安装提示需要openssl的问题

新版本的nginx安装的时候未发现openssl的路径&#xff0c;有两种方式解决 方式一&#xff1a; 找到本地nginx的解压目录中 &#xff0c;例如我的放到root下面了。 进入 /root/nginx1.24.0/auto/lib/openssl/conf 目录下修改内容 &#xff0c;这两行都需要修改&#xff0c;…