前端打印
生成图片打印
所见即所得,体验效果好
无需重复调样式,减少工作量
问题图片模糊,内容截断,文字大小缩放
计算获取A4纸的长度(px)和高度(px)
A4的标准尺寸: 210mm * 297mm
屏幕的dpi: 1英寸(2.54cm)内有多少个像素px
获取屏幕的dpi后即可计算出A4纸的物理长度对应的屏幕显示长度
屏幕显示长度 = (dpi/2.54)*21
const getDpi = () => {
if ( window.screen.deviceXDPI) {
return [window.screen.deviceXDPI, window.screen.deviceYDPI];
}
const node = document.createElement( "div" );
node.style = 'width:1in;height:1in;visibility:hidden;position:fixed;';
document.body.appendChild(node);
const dpi = [node.offsetWidth, node.offsetHeight];
document.body.removeChild(node);
return dpi;
}
const getA4Size = () => {
const [x, y] = getDpi();
return [(x/2.54)*21, (y/2.54)*29.7];
}
生成图片
按照a4纸宽度设置要打印的dom节点,再调用html2canvas绘制生成一张长图
字体模糊: 可放大canvas画布再绘制图片
分页
根据a4高度切分图片分页
避免切割到内容:从图片尾部开始遍历->判断该行是否存在非白色的像素点(判断该点是否为文字)->直到找到空白行
async getImages() {
const scale = 2;
const a4Width = this.a4Size[0]*scale;
const a4Height = this.a4Size[1]*scale;
this.dom.style.width = `${this.a4Size[0]}px`;
this.dom.style.display = 'block';
const canvas = await html2canvas(this.dom, {
useCORS: true,
allowTaint: true,
scale,
backgroundColor: 'rgb(255, 255, 255)'
});
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const list = [];
let posY = 0;
while(posY <= height) {
const restHeight = height - posY;
let posY2 = posY + Math.min(a4Height, restHeight);
if(restHeight > a4Height) {
posY2 = this.getBlankRow(ctx, posY2, width);
}
const img = this.getPageImage(canvas, posY, posY2, a4Height);
list.push(img);
posY = posY2 + 1;
}
this.dom.style.display = 'none';
return list;
}
getBlankRow(ctx, y, width) {
const data = ctx.getImageData(0, y, width, 1).data;
let count = 0;
for(let i = 0; i < data.length; i=i+4 ) {
if (data[i] !== this.bgHex[0] || data[i+1] !== this.bgHex[1] || data[i+2] !== this.bgHex[2]) {
count++;
}
if(count > 10) {
return this.getBlankRow(ctx, y-1, width);
}
}
return y;
}
页眉页脚
使用CSSRule
使用canvas指令绘制
使用printJS打印图片
async toPrint() {
const imgList = await this.getImages();
printJS({
documentTitle: this.title,
printable: imgList,
type: 'image',
style: `
@media print {
@page {
size: A4;
margin: 10mm;
}
body {
margin: 0;
padding: 0;
}
}
`,
imageStyle: `
width: 100%;
margin: 0;
padding: 0;
`
})
}