前言
废话有时间再写,这个功能是在其他人分享的源代码的基础上修改的,只为了完成功能。
方法调用
var $el = document.getElementById("table");
exportToPDF($el);
jspdf打印
function exportToPDF(element) {
var pdf = jspdf.jsPDF('', 'pt', 'a4');
// A4纸张的宽度和高度
var A4_WIDTH = 592.28;
var A4_HEIGHT = 841.89;
// A4实际内容宽度
var CONTENT_WIDTH = 560;
// 距离PDF左边的距离,/ 2 表示居中
var baseX = (A4_WIDTH - CONTENT_WIDTH) / 2; // 预留空间给左边
var baseY = 15;
// 除去间距后,页面内容的实际高度
var CONTENT_HEIGHT = A4_HEIGHT - 2 * baseY;
// PDF内容宽度和在HTML中宽度的比值
var rate = CONTENT_WIDTH / element.getBoundingClientRect().width;
// 每一页的分页坐标, PDF高度, 初始值为根元素距离顶部的距离
var pages = [rate * getElementTop(element)];
//计算页面的高度
var pageHeight = Math.ceil(rate * A4_HEIGHT);
// 一页的高度, 转换宽度为一页元素的宽度
toCanvas(element, CONTENT_WIDTH).then(function (canvas) {
var width = canvas.width;
var height = canvas.height;
var data = canvas.data;
// 深度遍历节点的方法
traversingNodes(document.querySelectorAll("tr"));
// 对pages进行一个值的修正,因为pages生成是根据根元素来的,根元素并不是我们实际要打印的元素,而是element,
// 所以要把它修正,让其值是以真实的打印元素顶部节点为准
var newPages = pages.map((item) => item - pages[0]);
// 根据分页位置 开始分页
for (var i = 0; i < newPages.length; ++i) {
// 根据分页位置新增图片
addImage(
baseX,
baseY - newPages[i],
pdf,
data,
width,
height
);
// 对于除最后一页外,对 内容 的多余部分进行遮白处理
if (i < newPages.length - 1) {
// 获取当前页面需要的内容部分高度
var imageHeight = newPages[i + 1] - newPages[i];
console.log(12121, baseY + imageHeight, baseY * 2 + imageHeight);
// 对多余的内容部分进行遮白
addBlank(
0,
baseY + imageHeight,
A4_WIDTH,
A4_HEIGHT - imageHeight
);
}
// 若不是最后一页,则分页
if (i !== newPages.length - 1) {
// 增加分页
pdf.addPage();
}
}
pdf.save('a.pdf');
});
// 添加
function addImage(_x, _y, pdfInstance, base_data, _width, _height) {
pdfInstance.addImage(base_data, 'JPEG', _x, _y, _width, _height);
}
// 增加空白遮挡
function addBlank(x, y, _width, _height) {
pdf.setFillColor(255, 255, 255);
pdf.rect(x, y, Math.ceil(_width), Math.ceil(_height), 'F');
}
// 获取该元素到页面顶部的高度(注意滑动scroll会影响高度)
function getElementTop(contentElement) {
if (contentElement.getBoundingClientRect) {
var rect = contentElement.getBoundingClientRect() || {};
// 考虑滚动条对高度的影响
var topDistance = rect.top + window.scrollY;
return topDistance;
}
}
// 遍历元素节点
function traversingNodes(nodes, height) {
for (var element of nodes) {
var one = element;
// table的每一行元素也是深度终点
var isTableRow = one.nodeName == 'tr';
// 对需要处理分页的元素,计算是否跨界,若跨界,则直接将顶部位置作为分页位置,进行分页,且子元素不需要再进行判断
var { offsetHeight } = one;
// 计算出最终高度
var offsetTop = getElementTop(one);
// dom转换后距离顶部的高度
// 转换成canvas高度
var top = rate * offsetTop;
var rateOffsetHeight = rate * offsetHeight;
// 对于深度终点元素进行处理
if (isTableRow) {
// dom高度转换成生成pdf的实际高度
// 代码不考虑dom定位、边距、边框等因素,需在dom里自行考虑,如将box-sizing设置为border-box
updateTablePos(rateOffsetHeight, top);
}
// 对于普通元素,则判断是否高度超过分页值,并且深入
else {
// 执行位置更新操作
updateNormalElPos(top);
// 遍历子节点
traversingNodes(one.childNodes);
}
updatePos(height);
}
}
// 普通元素更新位置的方法
// 普通元素只需要考虑到是否到达了分页点,即当前距离顶部高度 - 上一个分页点的高度 大于 正常一页的高度,则需要载入分页点
function updateNormalElPos(top) {
if (
top - (pages.length > 0 ? pages[pages.length - 1] : 0) >=
CONTENT_HEIGHT
) {
pages.push(
(pages.length > 0 ? pages[pages.length - 1] : 0) + CONTENT_HEIGHT
);
}
}
function updateTablePos(eHeight, top) {
// 如果高度已经超过当前页,则证明可以分页了
if (top - (pages.length > 0 ? pages[pages.length - 1] : 0) >= CONTENT_HEIGHT) {
pages.push(
(pages.length > 0 ? pages[pages.length - 1] : 0) + CONTENT_HEIGHT
);
} else if (top + eHeight - (pages.length > 0 ? pages[pages.length - 1] : 0) > CONTENT_HEIGHT
&& top !== (pages.length > 0 ? pages[pages.length - 1] : 0)) {
// 若 距离当前页顶部的高度 加上元素自身的高度 大于 一页内容的高度, 则证明元素跨页,将当前高度作为分页位置
pages.push(top);
}
}
function updatePos(height) {
while (pages[pages.length - 1] + CONTENT_HEIGHT < height) {
pages.push(pages[pages.length - 1] + CONTENT_HEIGHT);
}
}
};
html2canvas转为图片
function toCanvas(element, width) {
if (!element) {
return Promise.resolve({ width: width, height: 0 });
}
return new Promise(function (resolve, reject) {
html2canvas(element, {
// allowTaint: true, // 允许渲染跨域图片
scale: 1.4, // 增加清晰度
dpi: 300,
useCORS: true // 允许跨域
}).then(function (canvas) {
// 获取canvas转化后的宽高
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
// html页面生成的canvas在pdf中的高度
var height = (width / canvasWidth) * canvasHeight;
// 转化成图片Data
var canvasData = canvas.toDataURL('image/jpeg', 1.0);
resolve({ width: width, height: height, data: canvasData });
}).catch(function (error) {
reject(error);
});
});
}