1 截图以生成报告
选中页面中的 DOM 元素并克隆
添加到预览页面 exportView 的 DOM 中 -- appendChild
let featSfEle = document.getElementById("exp-featSf");
const clonedEle = featSfEle.cloneNode(true);
clonedEle.style.width = '80%';
clonedEle.style.height = '80%';
fragmentFeat.appendChild(clonedEle);
【难题 1】性能优化:批量操作 DOM:尽可能将多个 DOM 操作合并为一个,减少回流和重绘的次数
创建文档片段,将克隆元素先全部追加到文档片段,之后一次性追加到真实 DOM
const fragmentFeat = document.createDocumentFragment(); // 创建文档片段
fragmentFeat.appendChild(clonedEle1); //追加DOM
fragmentFeat.appendChild(clonedEle2);
targetFeatTf.appendChild(fragmentFeat); //一次性追加真实DOM
【补】文档片段(Document Fragment)
-
轻量的、不可见的 DOM节点,但不属于DOM树的一部分
-
——> 不会触发重排和重绘
-
——> 被插入实际 DOM 树时,浏览器一次性地渲染
-
用途: 作为一个“临时的”DOM结构,实现 DOM 批处理
【难题 2】Echart 绘制的 canvas 不能用这个方法,会拿到一个空的 canvas
html2canvas 将包含 echart canvas 在内的一整个解码视图绘制成 canvas
js
html2canvas(decodeEle).then((canvas) => {
canvas.style.width = '100%';
canvas.style.height = '100%';
targetDecode.appendChild(canvas);
})
【难题 3】html2canvas 性能极差,页面卡顿
- 简化 DOM 结构,过滤掉不需要渲染的子元素---
ignoreElements - html2canvas 配置优化
useCORS: true:确保跨域图像能正确加载logging: false:关闭日志输出scale: 1:图像质量, 降低 scale 可以减少渲染时间- ......
2 PDF 导出
(1)使用 html2Canvas 和 JsPDF 库,转化为图片后保存PDF
- 安装
npm install html2canvasnpm install jspdf - 待导出DOM ---> Canvas:
html2canvas(DOM).then(canvas=>{}) - Canvas ---> 图片数据 pageData:
canvas.toDataURL('image/jpeg', 1.0); - 图片数据---> JsPDF 对象:
new JsPDF(...).addImage(pageData,...)
(2)PDF 的分页问题
-
leftHeight > pageHeight需要分页 -
pageHeight一页的最大容量, canvas 的宽和页高与 A4 比例保持一致canvasWidth / pageHeight = A4 宽 / A4 高 -
剩余未生成的 canvas 高度
leftHeight:初始化为原canvas 高,随后每生成一页- pageHeight
/**
path: src/utils/htmlToPdf.js
name: 导出页面为PDF格式
**/
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
const htmlToPdf = {
getPdf(title) {
html2Canvas(document.querySelector('#pdfDom'), {
allowTaint: true,
}).then(canvas => {
// 1.准备 判断分页 的数据
let canvasWidth = canvas.width; //整个html渲染成canvas的宽高
let canvasHeight = canvas.height;
//一页pdf最多可容纳多少高度
let pageHeight = canvasWidth / 592.28 * 841.89; //a4纸的尺寸[595.28,841.89]
//当前剩余的未生成PDF的canvas高,随着 PDF 页面的生成,这个值会逐渐减小
let leftHeight = canvastHeight;
//垂直偏移,每生成一页 PDF,这个值会向下移动一个页面的高度
let position = 0;
// 2. canvas转图片数据
// 自定义图片的宽度,并让其纵横比保持比例
let imgWidth = 500;
let imgHeight = 500 / canvasWidth * canvasHeight;
let pageData = canvas.toDataURL('image/jpeg', 1.0);
//3. 新建JsPDF对象,并添加图片数据
let PDF = new JsPDF('', 'pt', 'a4');
// 判断是否分页
if (leftHeight < pageHeight) { // 如果内容高度小于一页 PDF 高度,直接添加图片
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) //添加图片数据
}
// 如果内容高度大于一页 PDF 高度,需要分页
else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
// 如果剩余高度还大于 0,添加新的一页
if (leftHeight > 0) {
PDF.addPage()
}
}
}
//保存pdf文件
PDF.save(title + '.pdf')
})
}
};
export default htmlToPdf;
<template>
<div id="pdfDom" >
<!-- ... -->
</div>
</template>
<script>
import htmlToPdf from '@/utils/htmlToPdf'
//使用函数
htmlToPdf.getPdf('页面导出PDF文件名');
</script>