Javascript 带有文本的HTML画布图像因操作系统而异
我正在构建一个小的JS类,它包含一个Javascript 带有文本的HTML画布图像因操作系统而异,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我正在构建一个小的JS类,它包含一个元素,并使用它动态地绘制一些图像。特别是那些图像有背景(填充)和文本 完成此操作后,我想围绕此编写一些单元测试,以确保在给定一些输入的情况下,生成的输出(作为base64字符串)始终是相同的。这意味着,如果我想生成一个带有粉色背景和白色文本的图像,生成的输出总是一个带有白色文本的粉色图像,并且尺寸是相同的。换句话说,base64编码的字符串是相等的 我可以在本地运行这些测试,它们通过了(MacOS),但在我的Jenkins集成作业(在Linux上运行)中失败了
元素,并使用它动态地绘制一些图像。特别是那些图像有背景(填充)和文本
完成此操作后,我想围绕此编写一些单元测试,以确保在给定一些输入的情况下,生成的输出(作为base64字符串)始终是相同的。这意味着,如果我想生成一个带有粉色背景和白色文本的图像,生成的输出总是一个带有白色文本的粉色图像,并且尺寸是相同的。换句话说,base64编码的字符串是相等的
我可以在本地运行这些测试,它们通过了(MacOS),但在我的Jenkins集成作业(在Linux上运行)中失败了。这是因为图像的字体略有不同。在阅读了很多关于这方面的内容后,我怀疑这是因为不同的操作系统中字体的实现方式不同
请参见以下图片:
预期,在MacOS本地获得:
实际值,在Linux中获得:
您可以看到,我获得的实际图像比预期的高一点(文本下方的底部填充更小)。我目前使用的字体是“44px Arial”
见代码:
实施
单元测试:
作为expectedTransparentImageWithText
模块的全局变量,它保存我在MacOS中期望并获得的字符串base64值
我必须澄清,对于单元测试,我使用的是在节点上运行的,正如文档所说的,“尽可能地实现该API”(参考Canvas browser API)。我怀疑这就是字体不同的原因。我也得到了,它们之间没有100%的兼容性
有没有什么建议你可以给我更好的单元测试,并考虑字体a好吗?现在我只测试没有文本的图像,所以我可以避免遇到解释过的场景,但当然,这不是最好的做法。不同的操作系统使用不同的技术绘制字体。例如,MacOs使用亚像素,Windows使用ClearType。这使得使用画布进行指纹识别成为可能。也许像Docker这样的东西可以工作,测试将在相同的环境中运行,而不管主机操作系统是什么。我想Docker不会从主机操作系统继承字体之间的差异。不同的操作系统使用不同的技术来绘制字体。例如,MacOs使用亚像素,Windows使用ClearType。这使得使用画布进行指纹识别成为可能。也许像Docker这样的东西可以工作,测试将在相同的环境中运行,而不管主机操作系统是什么。我想Docker不会从主机操作系统继承字体之间的差异。
generateImage(backgroundColor, fontColor = "#000000") {
if (backgroundColor) {
this.drawBackgroundWithColor(backgroundColor);
}
this.drawTexOverBackground("Text to draw", X_POSITION, Y_POSITION, fontColor, "44px Arial");
return this.getCurrentCanvasAsBase64String();
}
drawBackgroundWithColor(backgroundColor){
if (backgroundColor) {
const context = this.getCanvasContext();
context.save();
context.fillStyle = backgroundColor;
context.fillRect(0, 0, this.width, this.height);
context.restore();
}
}
drawTexOverBackground(text, x, y, hexColor, font = this.font) {
const context = this.getCanvasContext();
context.save();
context.font = font;
context.textBaseline = "top";
context.fillStyle = hexColor;
context.fillText(text, x, y);
context.restore();
}
it('should create a basic pink background with black text', () => {
const backgroundGenerator = new ImageGenerator();
const createdBackground = backgroundGenerator.generateImage("#FFC0CB");
assert.equal(createdBackground, expectedTransparentImageWithText);
});