HTML5 Canvas 如果使用 jspdf 添加到 pdf 文件,字体会变得模糊
HTML5 Canvas font gets blurry if added to a pdf file with jspdf
我确实构建了一个函数来缩小字体大小,直到文本宽度小于 canvas 宽度。此字体正在添加到包含二维码的 canvas。
此 canvas 被添加到 pdf 文件中。
我遇到的问题是,虽然二维码保持清晰,但文本会变得模糊。
这是生成的带有文本的二维码的屏幕截图:
为了对比,这里是在word中创建的相同大小、相同字号的二维码:
全尺寸屏幕截图,以查看它们的尺寸是否相同。均取自 pdf 文件:
Code, Word
生成此二维码+文字的代码如下:
printQRCode(){
const width = 150; // will be dynamic in the future
const ratio = 8 / 100;
const fontSize = width * ratio; // desired font size if the text fits the canvas
const text = `[${this.getCode()}]`;
toCanvas(text,
{errorCorrectionLevel: 'H', width},
(_err, canvas) => {
const ctx = canvas.getContext('2d');
this.setOptimalFontSizeForCanvas(ctx, fontSize, text, width); // shrinks the font size if the text is to long
ctx.fillText(text, this.getCenterPositionForCanvasText(ctx, text, width), width - 5);
const contentDataURL = canvas.toDataURL('image/png');
const pdf = new jsPDF('p', 'px', 'a4');
pdf.addImage(contentDataURL, 'PNG', 0, 0, canvas.width, canvas.height);
pdf.autoPrint();
pdf.output('dataurlnewwindow');
});
}
setOptimalFontSizeForCanvas(ctx: CanvasRenderingContext2D, fontSize: number, text: string, width: number){
ctx.font = fontSize + 'px Arial';
do{
fontSize--;
ctx.font = fontSize + 'px Arial';
}while(ctx.measureText(text).width>width- Math.floor(width / 10));
}
我需要更改哪些内容才能使文本不再模糊?
编辑:
我确实记录了 canvas 的数据 URL,我看到的第一件事是原始 canvas 比打印到 pdf 文件的要小得多。我尝试将png的输入单位更改为'pt'。这确实使 canvas 变小了,但它仍然比来自 dataURL 的图像大。
如何计算传递给 png 函数的宽度和高度需要多大?
当前解决方法:
我将输入单位格式改为px,从dataURL中计算生成的代码与原始大小的大小因子,发现生成的代码正好大了1.7784倍。
所以我只用这个系数除以大小
pdf.addImage(contentDataURL, 'PNG', 0, 0, Math.floor(canvas.width / 1.7784), Math.floor(canvas.height / 1.7784));
它会起作用的。但我觉得有更好的方法。
编辑:
我找到了更好的方法。当提供宽度和高度为 0 时,尺寸将设置为添加图像的实际尺寸:
pdf.addImage(contentDataURL, 'PNG', 0, 0, 0, 0);
我确实构建了一个函数来缩小字体大小,直到文本宽度小于 canvas 宽度。此字体正在添加到包含二维码的 canvas。
此 canvas 被添加到 pdf 文件中。
我遇到的问题是,虽然二维码保持清晰,但文本会变得模糊。
这是生成的带有文本的二维码的屏幕截图:
为了对比,这里是在word中创建的相同大小、相同字号的二维码:
全尺寸屏幕截图,以查看它们的尺寸是否相同。均取自 pdf 文件:
Code, Word
生成此二维码+文字的代码如下:
printQRCode(){
const width = 150; // will be dynamic in the future
const ratio = 8 / 100;
const fontSize = width * ratio; // desired font size if the text fits the canvas
const text = `[${this.getCode()}]`;
toCanvas(text,
{errorCorrectionLevel: 'H', width},
(_err, canvas) => {
const ctx = canvas.getContext('2d');
this.setOptimalFontSizeForCanvas(ctx, fontSize, text, width); // shrinks the font size if the text is to long
ctx.fillText(text, this.getCenterPositionForCanvasText(ctx, text, width), width - 5);
const contentDataURL = canvas.toDataURL('image/png');
const pdf = new jsPDF('p', 'px', 'a4');
pdf.addImage(contentDataURL, 'PNG', 0, 0, canvas.width, canvas.height);
pdf.autoPrint();
pdf.output('dataurlnewwindow');
});
}
setOptimalFontSizeForCanvas(ctx: CanvasRenderingContext2D, fontSize: number, text: string, width: number){
ctx.font = fontSize + 'px Arial';
do{
fontSize--;
ctx.font = fontSize + 'px Arial';
}while(ctx.measureText(text).width>width- Math.floor(width / 10));
}
我需要更改哪些内容才能使文本不再模糊?
编辑:
我确实记录了 canvas 的数据 URL,我看到的第一件事是原始 canvas 比打印到 pdf 文件的要小得多。我尝试将png的输入单位更改为'pt'。这确实使 canvas 变小了,但它仍然比来自 dataURL 的图像大。
如何计算传递给 png 函数的宽度和高度需要多大?
当前解决方法:
我将输入单位格式改为px,从dataURL中计算生成的代码与原始大小的大小因子,发现生成的代码正好大了1.7784倍。
所以我只用这个系数除以大小
pdf.addImage(contentDataURL, 'PNG', 0, 0, Math.floor(canvas.width / 1.7784), Math.floor(canvas.height / 1.7784));
它会起作用的。但我觉得有更好的方法。
编辑:
我找到了更好的方法。当提供宽度和高度为 0 时,尺寸将设置为添加图像的实际尺寸:
pdf.addImage(contentDataURL, 'PNG', 0, 0, 0, 0);