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

先安装依赖

javascript 复制代码
npm install --save html2canvas
npm install jspdf --save

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

components/pdf 创建pdf文件夹

javascript 复制代码
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.28
			const 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获取到所有的节点,即可大致知道将要生成多少页的PDF
			let 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, // 将分辨率提高到特定的DPI
				logging: 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 ,这里要减掉 40
				var 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 = true
								for (var j = 0; j < canvas.width; j++) {
									var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data

									if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
										isWrite = false
										break
									}
								}
								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文件中引入

javascript 复制代码
import htmlToPdf from '@/components/pdf/pdf.js'

app.use(htmlToPdf);

在需要的页面绑定id 事件

javascript 复制代码
	import {
		getCurrentInstance
	} from 'vue';

	const {
		appContext
	} = getCurrentInstance();

// 下载报告
	const down = () => {
        let target = document.querySelector('#targetDom'); //ID获取节点对象
		appContext.config.globalProperties.$createPdf(target, '报告');
}
相关推荐
~烈18 小时前
Acrobat Pro DC 便携精简版 PDF 专业处理工具安装教程
pdf·acrobat pro dc·pdf 专业处理工具
我不是QI19 小时前
Master PDF Editor 逆向复现
汇编·安全·pdf
蓝创工坊Blue Foundry20 小时前
多个同模板 PDF,怎样批量提取同一类字段到 Excel
运维·数据库·pdf·自动化·ocr·excel
asdzx672 天前
Python PDF 拆分实战指南:单页拆分与按需页码范围拆分
开发语言·python·pdf
慧都小妮子3 天前
Aspose.CAD for .NET 26.6 更新发布
pdf·.net·3d渲染·cad·pdf导出·ifc编辑
蝉蜕日记3 天前
AccumuPDF高级版 v2.57 | 视图文转换PDF,合并分割压缩
android·智能手机·pdf·生活·软件需求
蓝创工坊Blue Foundry3 天前
PDF 批量提取指定内容到 Excel:按字段整理多个 PDF 的方法
pdf·ocr·excel·文心一言·paddlepaddle·paddle
Am-Chestnuts3 天前
AI长回答批量导出PDF与长图:多轮内容整理和免费Markdown备份
人工智能·pdf·aigc
zyplayer-doc3 天前
研发接口文档怎么长期维护:zyplayer-doc把API、Markdown和变更记录放进同一个知识库
大数据·数据库·人工智能·笔记·pdf·ocr
蜡台3 天前
uniapp pdf文件预览组件
pdf·uni-app·合同·pdfh5