最近遇到公司的一项业务,需要下载凭证信息,听到下载就安心的交给了后端同志,我只负责安心的调个接口就好。功能实现后不太满意,因为生成的个excel,重新要求生成PDF,后端同志说不太好实现那就前端来吧,查询后决定使用html2canvas和jspdf。
生成一切顺利,获取dom,生成图片,生成PDF,但是问题来了,在22寸屏和14寸屏下生成的PDF内容一样但是字体不一样大。最后考虑到,元素使用的百分比单位,在不同尺寸在宽度不一样造成缩放问题,那么如何保持一致呐?PDF是由图片转的,图片是由canvas来的,那么确保生成出来的canvas宽高一致不久好了嘛。
打印下发现宽高确实不一样
html2canvas(element, {
scale: 2,
logging: true
}).then(function (canvas) {
console.log(canvas);
//打印结果21寸<canvas width="3840" height="1874" style="width: 1920px; height: 937px;"></canvas>
//打印结果14寸<canvas width="3072" height="1446" style="width: 1536px; height: 723px;"></canvas>
那么就知道问题所在了,因为单位使用了百分比,导致获取的宽高不一致而影响下载后的PDF大小也不一致。那么既然是宽高的问题,那么我们直接固定死宽高,这样下载就不会出现不一样的问题了,在element转换为canvas时确定的宽高,那么研究html2canvas的源码发现
defaultOptions = {
backgroundColor: '#ffffff',
cache: opts.cache ? opts.cache : CacheStorage.create(instanceName, resourceOptions),
logging: true,
removeContainer: true,
foreignObjectRendering: false,
scale: defaultView.devicePixelRatio || 1,
windowWidth: defaultView.innerWidth,
windowHeight: defaultView.innerHeight,
scrollX: defaultView.pageXOffset,
scrollY: defaultView.pageYOffset,
x: left,
y: top,
width: Math.ceil(width),
height: Math.ceil(height),
id: instanceName
看着默认选项感觉有戏,注释掉后来一份重写的(主要修改windowWidth,windowHeight,width,height)打印后发现值在不同尺寸下不会改变了,那么我是找对了地方。那直接修改完事岂不美滋滋,但是想想不对啊,项目用的vue,这是npm引用第三方啊,我本地改好没卵用,正式环境出错那就凉了。不能直接改源码那就另找出路,关于width和height好办,html2canvas文档有说,可以直接设置
html2canvas(element, {
scale: 2,
width: 1536,
height: 700,
logging: true
}).then(function (canvas) {
windowWidth,windowHeight调用的是defaultView里面的值,向上查看源码发现正确的路径是element.ownerDocument.defaultView.*,打印一下element.ownerDocument.defaultView看看内容
发现了我们需要的属性,那么最后一步,在我们获取到元素时先把他的这两的属性给固定死就好了
export function ExportSavePdf(htmlTitle, currentTime){
var element = document.getElementById("pdfCentent");
element.ownerDocument.defaultView.devicePixelRatio = 1.25;
element.ownerDocument.defaultView.innerWidth = 1536;
element.ownerDocument.defaultView.innerHeight = 700;
html2canvas(element, {
scale: 2,
width: 1536,
height: 700,
logging: true
}).then(function (canvas) {