前阵子我做了个开源项目——在线编辑简历的小工具(http://www.deartami.com),需要将html页面转换成pdf文件并下载,遇到的一些坑,跟大家分享一下。
清晰度低
开始的思路是这样的,使用html2canvas将html转换成canvas,然后再将canvas转换成图片,将图片保存为pdf格式
html2canvas(target, {
scale: 4
}).then(function(canvas) {
let context = canvas.getContext('2d'); // 关闭抗锯齿
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
PDF.addImage(canvas, 'JPEG', 0, 0, width, height);
PDF.save('简历.pdf');
});
但是效果非常模糊,查了一番,看到网上的道友们说先放大,于是我将scale值增大到4,虽然效果变好了,但还是远远达不到要求,我需要的是原画质!
于是我换成了jsPDF插件,此插件依赖于html2canvas。
let pdf = new jsPDF({
orientation: 'p',
unit: 'pt',
format: 'a4',
precision: '12',
putOnlyUsedFonts:false,
floatPrecision: "smart" // default is 16
});
pdf.html(target, {
html2canvas: {
scale: 0.75
},
callback: function (pdf) {
pdf.save('大米简历.pdf');
}
});
好了,原画清晰度!非常棒!可以直接访问简历小工具(http://www.deartami.com)体验一番。
字体放大
现在画质解决了 但是我发现文字都被放大了~
~阿噢~
怎么整?
查了一下jsPDF的issues,看到有一个解答正好是我需要的(issues/2632):
pdf.html(target, {
html2canvas: {
scale: 0.75
},
callback: function (pdf) {
pdf.save('大米简历.pdf');
}
});
我将scale参数设为0.75就正常了。
不支持中文
然而,我很快就发现,这种解决方案不支持中文啊,我滴个神啊~
怎么办?
能咋办?搞呗~我就哼哧哼哧地爬起来各种翻文档,原来在README.md有说明:
要自己加字体。好吧......
我使用的是思源字体:https://github.com/Pal3love/S...
使用官方提供的fontconverter:https://rawgit.com/MrRio/jsPD...
将.ttf文件转换成.js文件sourcehansanscn-normal-normal.js。注意⚠️:.ttf的文件名要先改成小写,否则无效
这个字体包很大,为了不影响首屏的加载速度,所以引入的时候我独自打包了。
import(/* webpackChunkName: "sourcehansanscnNormal"*/'@/util/sourcehansanscn-normal-normal').then((source) => { source.SourceHanSansCN();});
.pdfcontent{ font-family:'SourceHanSansCN-Normal' /*pdf转换插件不能识别中文*/}
注意⚠️:不要使用商用字体哦~
字体加粗
好了,似乎很很完美了~Y~
然鹅,还是有问题,打印出来的pdf不能识别加粗字体,也就是font-weight: bold设置无效。
继续查找issues,无解,只能引入两种不同的字体包,一种是正常的,一种是加粗的,单独设置font-family属性
.pdfcontent{
font-family:'SourceHanSansCN-Normal' /*pdf转换插件不能识别中文*/
}
.pdfcontent strong,
.pdfcontent h1,
.pdfcontent h2,
.pdfcontent h3,
.pdfcontenth4{
font-family: 'sourcehansanscn-medium';
}
到此为止~一切真的完美了~编译通过就等上线啦~嘿嘿嘿~
压缩打包运行npm run build~哒哒哒哒~
~哒~
~哒~
~哒~
运行失败,内存溢出啦......==!!!
内存溢出
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
哇,那两个字体文件太大了,我就说嘛!
我就骂骂咧咧地打开vue-cli的issues,还真有解决方案:issues/1453
修改package.json中的script,将max\_old\_space\_size增大至4096,你可根据自己的文件修改大小值哈~
"build": "node --max\_old\_space\_size=4096 node\_modules/@vue/cli-service/bin/vue-cli-service.js build --open"
终于~到了这里~一切就绪~我可以上线啦~
关于源码,后续我会放到https://github.com/aBigRice/r...
不过在写这篇文章的时候我还没有上传~~~~
嘿嘿~~
那你关注我嘛~~~~~