【问题标题】:Fractional font sizes html5 canvas?小数字体大小html5画布?
【发布时间】:2013-03-04 01:41:39
【问题描述】:

我遇到了不同浏览器如何在 HTML5 Canvas 上呈现字体大小的问题。特别是在字体大小不是整数的情况下。例如“8.5px Arial”、“2.23em Arial”等。

对于 canvas.font= FontSize + "px Arial";其中 FontSize 是 (8.1, 8.2, 8.3, ...) 我希望得到线性结果,但是唯一始终存档的浏览器是 IE ! ( 我知道 )。 Firefox 四舍五入低于 11.2 像素,但超出此范围是线性的。 Chrome 和 Safari 仅将字体缩放为整数值。

四舍五入规则似乎设置为像素并向下四舍五入到 0.5 以下的最接近整数

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

浏览器在 pt、px、em 和 % 字体大小之间的行为至少是一致的。 [编辑:除了 Safari 不呈现 % 大小]

[顺便说一句:所有字体一旦放大一点就会显得有点粗体。当我们从 17.4px 到 17.5px .. 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>

像素比例 点刻度 em 比例 - 1em = 5px Arial 百分比比例 - 100% = 5px Arial

【问题讨论】:

    标签: html animation canvas fonts scale


    【解决方案1】:

    我认为你们应该为我做我的工作;)无论如何,这就是我解决问题的方法,尽管它有点小技巧,但我仍然会描述一些问题。

    回顾一下(因为问题可能不清楚)我试图将字体大小乘以一些浮点数来放大和缩小文本。但这会导致结果不稳定,因为大多数情况下会将字体大小四舍五入到最接近的整数值。

    例如。

    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。

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

    所有浏览器都呈现给定的文本字符串(例如“EXAMPLE TEXT”)并且长度略有不同,这使问题更加复杂。

    解决办法

    在初始化期间以标准字体大小 (zoom=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 乘以与我们在此渲染过程中的字体大小相同的缩放因子。

    我对所有这一切的奖励是它具有标准化浏览器行为的所有差异的效果......几乎。

    问题

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

    但是,这已经是我所拥有的巨大改进。

    此外,您还需要将 tmpCanvas 剪辑到 mainCanvas,否则您的浏览器会在尝试创建和复制百万像素值的文本时停止运行,只是为了让一个字符全屏显示.

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-06
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      相关资源
      最近更新 更多