一,导出pdf
1,下载安装domToImage
npm i domToImage
2,实际使用,使用useDomToImageExport方法按照A4纸大小导出
其中使用了分页截断页面,在需要分割dom部分采用插入一个空白dom的方式实现分页效果,用于计算分页的元素需要添加class = 'row'用于计算元素分割
//生成PDF
const useDomToImageExport = async (dom, fileName, fixedHeight) => {
// const dom = domItem.cloneNode(true)
const A4_PAPER_SIZE_ENUM = {
width: 592.28, //592.28
height: 841.89 // 841.89
}
const contentWidth = dom.scrollWidth
const contentHeight = dom.scrollHeight
// 一页pdf显示html页面生成的canvas高度
let pageHeight = (contentWidth / A4_PAPER_SIZE_ENUM.width) * A4_PAPER_SIZE_ENUM.height
// const pageHeight = 1150
if (fixedHeight) {
pageHeight = fixedHeight
}
// 未生成pdf的html页面高度
let leftHeight = contentHeight
// 页面偏移
let position = 0
const imgWidth = A4_PAPER_SIZE_ENUM.width
const imgHeight = (A4_PAPER_SIZE_ENUM.width / contentWidth) * contentHeight
// 将所有不允许被截断的元素进行处理
let wholeNodes = dom.querySelectorAll('.row')
for (let i = 0; i < wholeNodes.length; i++) {
//1、 判断当前的不可分页元素是否在两页显示
let topPageNum = Math.ceil(wholeNodes[i].offsetTop / pageHeight)
let 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')
let hr = document.createElement('div')
hr.style.borderBottom = '1px solid'
hr.style.borderBottomColor = window.getComputedStyle(wholeNodes[i], null).borderBlockEndColor
hr.style.width = '100%'
hr.className = 'emptyDiv'
newBlock.className = 'emptyDiv'
newBlock.style.background = '#fff'
newBlock.style.borderLeft = '3px solid #fff'
newBlock.style.borderRight = '3x solid #fff'
newBlock.style.width = '101%'
newBlock.style.marginLeft = '-2px'
// 3、计算插入空白块的高度 可以适当流出空间使得内容太靠边,根据自己需求而定
let _H = Math.abs(topPageNum * pageHeight - wholeNodes[i].offsetTop) //Math.abs()
// let _H = wholeNodes[i].offsetHeight
newBlock.style.height = _H + 12 + 'px'
divParent.insertBefore(newBlock, wholeNodes[i])
divParent.insertBefore(hr, wholeNodes[i])
}
}
await domtoimage
.toPng(dom, {
bgcolor: '#ffffff',
quality: 1,
scale: 2
})
.then(function(canvas) {
// 移除空白div
let emptyNodes = dom.querySelectorAll('.emptyDiv')
for (let i = 0; i < emptyNodes.length; i++) {
let divParent = emptyNodes[i].parentNode
divParent.removeChild(emptyNodes[i])
}
const PDF = new jsPDF('p', 'pt', 'a4')
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
PDF.addImage(canvas, 'JPEG', 0, 0, imgWidth, imgHeight)
} else {
// 超过一页时,分页打印
while (leftHeight > 0) {
PDF.addImage(canvas, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= A4_PAPER_SIZE_ENUM.height
if (leftHeight > 0) {
PDF.addPage()
}
}
}
PDF.save(fileName + '.pdf')
})
}
3,如果dom此时不在页面上的时候需要直接导出的话可以使用虚拟节点去处理
因为此时需要导出的dom还未存在于页面上,需要虚拟dom渲染一次导出的组件,则需要在导出的组件上emit finishedrender 在虚拟组件渲染完成之后再触发导出
//导出文件 静默 导出pdf 需要在组件上emit finishedrender
const useExport = async (component, fileName) => {
//获取默认时间作为文件名
const getSendTime = (time = +new Date()) => {
var date = new Date(time + 8 * 3600 * 1000) // 增加8小时,转换到东八区
return date
.toJSON()
.substr(0, 19)
.replace('T', ' ')
}
fileName = fileName || getSendTime()
//创建包裹容器 降低层级不显示到页面上
const container = document.createElement('div')
container.style.position = 'fixed'
container.style.zIndex = '1'
const BODY = document.body
//自定义渲染完成回调
const vnodeMounted = async () => {
await useDomToImageExport(container, fileName)
//移除节点
render(null, container)
BODY.removeChild(container)
}
let props = {
onRenderFinished: vnodeMounted
}
const vnode = h(component, props)
render(vnode, container)
BODY.appendChild(container)
}
二,导出图片
1,导出图片选择插件html2canvas
npm i html2canvas
2,实际使用
type则为导出的图片类型
//生成图片
const generateImage = async (dom, types = 'png', fileName = 'file') => {
const domCopy = dom.cloneNode(true)
const contentWidth = `${dom.scrollWidth}px`
const contentHeight = `${dom.scrollHeight}px`
domCopy.style.width = contentWidth
domCopy.style.height = contentHeight
//避免找不到dom 成功之后再移除
document.body.appendChild(domCopy)
await html2canvas(domCopy)
.then((canvas) => {
let url = canvas.toDataURL(`image/${types}`, 1)
let aLink = document.createElement('a')
aLink.style.display = 'none'
aLink.href = url
// 下载图片
aLink.download = `${fileName}`
document.body.appendChild(aLink)
aLink.click()
document.body.removeChild(aLink)
document.body.removeChild(domCopy)
})
.catch((e) => {
useError(e)
})
}