问题背景:在进行预览打印,会遇到内容会被分页处截断,这个时候需要将被截断的内容向下移动,以此防止被分页分割线截断。 话不多说直接上代码
/**
* @description 由于dom结构的大小宽高不固定,所以在不能被截断的元素上添加info-table-item,根据该标识遍历子节点中class为info-table-item的元素,计算出info-table-item的元素距离顶部的偏移量,如果(元素a距离上方或上层控件的位置+元素a本身的高度小于A4纸的高度,并且下一个元素距离上方或上层控件的位置+下一个元素本身的高度大于A4纸的高度),则在两个元素中间插入一个空白块,空白的高度通过计算,为a4纸的高度减去元素a的offsetTop + offsetHeight,我们可以在计算出的高度上插入占位高度,避免下一页内容挨着分割线
* @param {*} ele 要生成pdf的DOM元素
* @param {*} wholeNodes 添加info-table-item标记可能有空白块的节点内容元素
* @param {*} func 回调返回的base64字符串,用于打印预览
*/
export function computePrint(ele, wholeNodes, func) {
const A4_WIDTH = 592.28
const A4_HEIGHT = 841.89
// 根据A4的宽高计算DOM页面一页应该对应的高度
let pageHeight = ele.offsetWidth / A4_WIDTH * A4_HEIGHT
// 定义一个参数emptyDomHeight用来计算新增空白块的总高度
let emptyDomHeight = 0
for (let i = 0; i < wholeNodes.length; i++) {
// 1、 判断当前的不可分页元素是否在两页显示
const topPageNum = Math.ceil((wholeNodes[i].offsetTop) / pageHeight)
const bottomPageNum = Math.ceil((wholeNodes[i].offsetTop + wholeNodes[i].offsetHeight) / pageHeight)
if (topPageNum !== bottomPageNum) {
// 说明该dom会被截断
// 2、插入空白块使被截断元素下移
let divParent = wholeNodes[i].parentNode
let newBlock = document.createElement('div')
newBlock.className = 'empty-div'
newBlock.style.background = '#fff'
// 3、计算插入空白块的高度 可以适当流出空间使得内容太靠边,根据自己需求而定
let _H = topPageNum * pageHeight - wholeNodes[i].offsetTop
// 计算新增空白区的总高度
emptyDomHeight = emptyDomHeight + _H + 30
newBlock.style.height = _H + 30 + 'px'
divParent.insertBefore(newBlock, wholeNodes[i])
// console.log('for循环内的空白高度', _H, emptyDomHeight, divParent)
}
}
html2canvas(ele, {
allowTaint: false,
scale: 1,
dpi: 300,
backgroundColor: '#fff',
height: ele.clientHeight + 50,
windowHeight: ele.clientHeight + 50
// scrollY: -scrollY
}).then((canvas) => {
// dom 已经转换为canvas 对象,可以将插入的空白块删除了
let emptyDivs = document.querySelectorAll('.empty-div')
for (let i = 0; i < emptyDivs.length; i++) {
emptyDivs[i].style.height = 0
emptyDivs[i].parentNode.removeChild(emptyDivs[i])
}
let contentWidth = canvas.width
let contentHeight = canvas.height
let pageHeight = (contentWidth / 592.28) * 841.89
let leftHeight = contentHeight
let position = 0
let imgWidth = 595.28
let imgHeight = (592.28 / contentWidth) * contentHeight
let pageData = canvas.toDataURL('image/jpeg', 0.5)
let PDF = new JsPDF('', 'pt', 'a4')
if (leftHeight < pageHeight) {
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
if (leftHeight > 0) {
PDF.addPage()
}
}
}
const buffer = PDF.output('datauristring')
func(buffer)
// PDF.save('报告.pdf')
})
}
打印内容区
会被截断的内容
<div class="info-table-item">
<div class="info-table-item">
<div class="info-table-item">
<div class="info-table-item">
.......