jsPDF将html页⾯⽣成pdf⽂件的前端解决⽅案及html2canvas如
何真正解决跨。。。
是⼀个可以把html转成pdf的插件,有⼈多⼈在⽤。
GitHub:
官⽅⽂档:
但是⽼外做的很多东西没考虑过英⽂之外的语⾔,这个也不例外,不⽀持中⽂,⽽且页⾯还原度也不是很好。
⽹上实例导出的是 A4 ⼤⼩,⽤到的是,以及需要库。其实就是把需要导出的⽹页,利⽤ html2canvas ⽣成图⽚,在 addImage ⾄PDF 中。⾄于为什么需要先转成图⽚呢,直接⽹页转不是很好吗,还能⽂字复制。因为不⽀中⽂,⽽且,样式还原度也不⾼。当然,执意于⽂本复制,⽹上也有解决⽅式(搜索关键字:jsPDF 中⽂)。
所以常⽤的解决⽅案就是:曲线救国: html2canvas + jsPdf
既然你不⽀持中⽂,那我把页⾯转成图⽚,怕不怕,图⽚再导出PDF照样中!这种⽅式很常见、很省事,问题也很多图⽚拉伸、模糊,最重要这样导出的PDF是没有灵魂的,因为他⾥⾯的内容都是图⽚,不能复制。对于pdf操作要求⽐较⾼的,这种⽅案就不⼤适合。如果你喜欢这种可以参照这篇⽂章,写的很详细。
采⽤这种⽅案也有⼀些问题需要处理,这⾥记录下,给后来⼈避坑。
1、html2canvas⽣成图⽚模糊的问题
这个问题⼤多数都会遇到,可以看我之前的博客处理:
2、html2canvas偶尔⽣成⼤量空⽩漏掉⼀些元素问题
在使⽤过程我发现有时候当滚动到底部时,⽣成的图⽚就会存在⼤量空⽩,漏掉很多元素
解决⽅案就是在⽣成图⽚前滚动⾄顶部使⽣成图⽚的元素进⼊渲染区域内。添加如下代码即可:
document.documentElement.scrollTop = 0
3、html2canvas⽣成图⽚⾥包含跨域图⽚的处理
这个问题也⽐较奇怪,在很多同版本浏览器上均可以⽣成跨域图⽚,但是在个别电脑上同版本浏览器也不⾏。会报跨域的错误,因为我们图⽚都是存储在阿⾥云的oss上
Access to image at '......aliyuncs/image/base/be6f..f.jpeg'
from origin '...:3001' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
⽹上很多各种解决⽅案也不靠谱。所以最后还是⾃⼰看源码,在html2canvas官⽹:html2canvas.hertzen/,下载源码,这⾥先看⼀下之前写的博客,涉及到在线图⽚跨域转base64格式的问题:
通过之前这篇博客就可以看到问题,那么其实我们只要改下⾯2段代码即可
if (isInlineBase64Image(src) || useCORS) {
// ssOrigin = 'anonymous';
}
// img.src = src;
img.src = src + '?v=' + Math.random();
注释的为原代码,下⾯的为修改后的代码即可。
4、jsPdf分页问题
页⾯过长,就涉及分页问题。因为 A4 是有固定页⾯⼤⼩的(宽:595.28, ⾼:841.89),保存的内容⾼度(缩放⾄A4宽度)超过该长度,则会出现截断问题。
解决⽅式其实不多,分情况⽽定。其实最简单的⽅式是不分页。不是吗?不分页,啥问题都没。这个问题就是,为什么要分页?讲真,没有分页需求,也没有打印需求,没必要分页,不是吗?整个页⾯导成图⽚就⾏。
不分页就是将元素宽⾼作为pdf⽂件的宽⾼就⾏
const pdf = new jsPDF('', 'pt', [contentWidth, contentHeight])
如果确实要分页的话,如果是纯静态页⾯,还⽐较简单,根据 A4 的尺⼨⽐例,预留好间隔,这样,裁剪的时候,便不会出现⽂本或者其他内容被裁成两半。
如果是动态页⾯的话就⽐较复杂,前端实现⽅案就并不太合适了,建议采⽤后端实现⽅案。
5、实例代码
downPdf () {
let _this = this
document.documentElement.scrollTop = 0
let canvas = ateElement("canvas")
let context = Context("2d")
let _articleHtml = ElementById('article-content')
let _w = _articleHtml.clientWidth
let _h = _articleHtml.clientHeight
let scale = 3
canvas.width = _w * scale
canvas.height = _h * scale
context.scale(scale, scale)
let opts = {
scale: 1,
width: _w,
height: _h,
canvas: canvas,
useCORS: true
pdf转html}
html2canvas(_articleHtml, opts).then(canvas => {
_atePdfAll(canvas, scale)
})
},
createPdfAll (canvas, scale) {
let contentWidth = canvas.width / scale
let contentHeight = canvas.height / scale
let pdf = new jsPDF('', 'pt', [contentWidth, contentHeight])
let pageData = DataURL('image/jpeg', 1.0)
pdf.addImage(pageData, 'JPEG', -9, 0, contentWidth, contentHeight)
pdf.save(`${this.detail.title}.pdf`)
},
此种⽅案纯前端实现,⽆需后端配合,并且页⾯还原度⽐较⾼,对于pdf操作要求不⾼的需求,还是⽐较合适的解决⽅案。
缺点就是⽆法复制,对pdf操作不⼤兼容,对于分页也不⼤友好,容易出现分割。其实后端实现⽅案也有蛮多,并且对于分页更友好,可以分情况选择不同⽅案。
发布评论