分数字体大小html5画布?

时间:2013-03-15 11:06:04

标签: html5 animation canvas fonts 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

我的画布应用程序正在执行一些程序化的动画变换(缩放和翻译)为了提高效率,尽量避免画布变换,虽然我怀疑它会解决问题,但我还没有通过设置html文本大小来测试这个CSS3(Canvas.font假设根据规范)

浏览器在pt,px,em和%字体大小之间的行为至少是一致的。 [编辑:除了Safari不会渲染%尺寸]

[旁白:所有字体看起来有点大胆一度炸毁了一下。当我们从17.4px变为17.5px时,Safari会拿出那个蛋糕.BAMB!]

我已经在下面添加了一些示例图片,但是我真的想要了解如何让所有浏览器更像IE的想法(再也没想过我会这么说) - 这是一个错误还是渲染字体的标准?

这是我的测试代码,可以复制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>

像素比例 pixel scale 点量表 point scale em scale - 1em = 5px Arial em scale 百分比 - 100%= 5px Arial percent scale

1 个答案:

答案 0 :(得分:6)

我认为很多人应该为我做我的工作;)无论如何,这是我如何解决问题,虽然它有点像黑客,但仍然有一些问题我会描述。

回顾一下(因为在问题中可能并不清楚)我尝试将字体大小乘以一些浮点数来放大和缩小文本。但由于大多数字体大小都是最接近的整数值,这导致了抖动结果。

例如。

var zoom = 1.02;
var font_size = 12;
context.font = (font_size * zoom) + "px Arial"; // 12.24px

zoom = 1.04(12.48px)将呈现与上述代码相同,而zoom = 1.06(12.75px)将向上舍入为13px。

这导致了值之间非常不希望的字体大小跳跃,而画布上的所有其他元素都被正确缩放。

所有浏览器都呈现给定的文本字符串,例如&#34;示例文本&#34;和略有不同的长度。

解决方案

在初始化期间以标准字体大小(缩放= 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);

根据行长度与预期行长度的距离,在主画布上拉伸或缩小生成的文本行。

在理想世界中,s总是等于1,因为预期的行长度总是与实际行长度相同。预期的行长度是我们的样本行长度iniLineLength乘以我们的字体大小在此渲染过程中的缩放因子。

我对这一切的奖励是,它具有规范浏览器行为的所有差异的效果......差不多。

问题

即使行长度归一化,行中每个字符的确切位置也不相同。在下图中给出效果。

enter image description here

然而,这已经是我所拥有的巨大进步。

此外,你想要将你的tmpCanvas剪辑到mainCanvas,否则你的浏览器会在尝试创建和复制你的百万像素文本时停下来,只是为了让一个角色全屏显示

考虑到这一点,您还可以根据需要设置您的tmp画布宽度和高度,以适应您要渲染的实际文本行,这将节省内存,时间等。