dav*_*zap 9 html5 fonts animation canvas scale
我遇到了不同浏览器如何在HTML5 Canvas上呈现字体大小的问题.具体而言,字体大小不是整数.例如"8.5px Arial","2.23em Arial"等.
对于canvas.font = FontSize +"px Arial"; 其中FontSize是(8.1,8.2,8.3,...)我期望得到一个线性结果,但是唯一一直存档的浏览器是IE!( 我知道 ).Firefox的收益率低于11.2px,但线性超出此范围.Chrome和Safari仅将字体缩放为整数值.
舍入规则似乎设置为像素并向下舍入到最接近.5的整数
我的画布应用程序正在执行一些程序化的动画变换(缩放和翻译)为了提高效率,尽量避免画布变换,虽然我怀疑它会解决问题,但我也没有通过设置仅使用CSS3的html文本大小来测试它( Canvas.font假设是根据规范)
浏览器在pt,px,em和%字体大小之间的行为至少是一致的.[编辑:除了Safari不会渲染%尺寸]
[旁白:所有字体看起来有点大胆一度爆炸了一下.当我们从17.4px变为17.5px时,Safari会拿出那个蛋糕.BAMB!]
我已经在下面附上了一些示例图片,但是我真的想要了解如何使所有浏览器更像IE的想法(再也没想过我会这么说) - 这是一个bug还是渲染字体的标准?
这是我的测试代码,可以复制PX字体大小的情况.
<!DOCTYPE html><html><head><script>
function display() {
var canvas = document.getElementById('test');
// For EM and % cases....
//canvas.style.font="5px Arial";
canvas.height = 1000;
var context = canvas.getContext('2d');
var minSize = 10;
var lineHeight = 100;
for(var a=minSize; a< 20; a+=0.1)
{
var font_size = Math.round(a*10000)/10000;
context.font = a + "px Arial";
context.fillText("A: EXAMPLE TEXT > " + font_size, 20, (font_size-minSize)*lineHeight);
}
}
</script></head><body onload="display()"><canvas id="test"></canvas></body></html>
Run Code Online (Sandbox Code Playgroud)
像素比例
点量表
em scale - 1em = 5px Arial
百分比 - 100%= 5px Arial

我认为很多人应该为我做我的工作;)无论如何,这里是我如何解决问题,虽然它有点像黑客,但仍然有一些我将描述的问题.
回顾一下(因为在问题中可能并不清楚)我试图通过一些浮点数乘以字体大小来放大和缩小文本.但是由于大多数字体大小都是最接近的整数值,这导致了抖动结果.
所以举个例子.
var zoom = 1.02;
var font_size = 12;
context.font = (font_size * zoom) + "px Arial"; // 12.24px
Run Code Online (Sandbox Code Playgroud)
zoom = 1.04(12.48px)将呈现与上面的代码相同,而zoom = 1.06(12.75px)将向上舍入到13px.
这导致值之间非常不希望的字体大小跳跃,而画布上的所有其他元素都正确缩放.
所有浏览器都呈现给定的文本字符串,例如"EXAMPLE TEXT"和略有不同的长度,这个问题更加复杂.
在初始化期间以标准字体大小(缩放= 1)渲染文本并测量行长度,让该值称为iniLineLength
在场景渲染过程中,我使用隐藏的画布将文本渲染到然后使用drawImage到主画布上,并在宽度上使用乘数.
tmpContext.font = (font_size * zoom) + "px Arial";
tmpContext.fillText(MyLineOfText,0, 0);
var s = (iniLineLength * zoom) / tmpContext.measureText(MyLineOfText) ;
mainContext.drawImage(tmpCanvas,x, y, pw * s, ph);
Run Code Online (Sandbox Code Playgroud)
根据行长度与预期行长度之间的距离,在主画布上拉伸或缩小生成的文本行.
在理想世界中,s总是等于1,因为预期的线长总是与实际的线长相同.预期的行长度是我们的样本行长度iniLineLength乘以我们的字体大小在此渲染过程中的缩放因子.
我所有这一点的好处是它具有规范浏览器行为的所有差异的效果......差不多.
即使行长度归一化,行中每个字符的确切位置也不相同.在下图中给出效果.

然而,这已经是我所拥有的巨大改进.
此外,你想要将你的tmpCanvas剪辑到mainCanvas,否则你的浏览器会在尝试创建和复制你的百万像素文本时停下来,只是为了让一个角色全屏显示.
考虑到这一点,您还可以根据需要设置您的tmp画布宽度和高度,以适应您要渲染的实际文本行,这将节省内存,时间等.