【问题标题】:Sub-pixel rendering in Chrome CanvasChrome Canvas 中的亚像素渲染
【发布时间】:2011-10-06 22:49:51
【问题描述】:

我想知道是否有人知道是否可以在 Chrome(和/或 Safari)的 HTML5 画布中启用子像素渲染。

Chrome 在 HTML 中进行亚像素渲染,而 FF 在 HTML 和 Canvas 渲染中都这样做。具体问题如下图:

【问题讨论】:

  • 我用谷歌搜索 subpixel chrome canvas 并且您 2 分钟前的帖子位于位置 1 - 第二个结果是您的答案(一个较旧的 stackoverflow 问题)
  • @sod - 谢谢。但是,这些解决方案需要进行手动文本渲染,这绝对不是我想要解决的问题

标签: javascript google-chrome canvas


【解决方案1】:

简短回答:不。不可能

这是让很多 Canvas 用户感到沮丧的两个主题之一。

任何类型的子像素渲染/抗锯齿都取决于浏览器。这意味着不同的浏览器倾向于以不同的方式呈现事物。

很多人都要求将抗锯齿功能设为可以针对特定上下文打开或关闭的选项。还没有这样的运气。

您需要特别注意 Chrome,因为它们处理亚像素渲染的方式在过去 4 个月中发生了巨大变化。如果您开始使用Chrome developer channel,您将获得他们不断尝试的东西的预览。他们在这方面做了很多测试,甚至推动了一些剧烈的回归变化,我已经complained about.

这里的要点是:

  1. Chrome 在亚像素渲染方面绝对“尚未完成”。说起来很糟糕,但你现在最好的选择是等待一段时间。
  2. 规范需要在这方面更加具体,以便在浏览器之间保持一定的一致性,因为现在任何亚像素渲染/抗锯齿都非常依赖于浏览器。在2008. 中有未解决的讨论,从那以后我没有任何进展。

【讨论】:

  • 这仍然是真的吗?
【解决方案2】:

我认为目前这是不可能的。

这是一个难题,因为画布为用户提供了如此多的低级控制。如果画布开始做这样的智能事情,它可能会破坏用户期望的其他一些功能。

考虑其他图形元素的亚像素渲染 - 根据应用程序的不同,程序员可能不希望这样,您当然也不希望将整个元素的亚像素渲染作为一个全有或全无的命题任意打开。想象一下获得特定像素的颜色 - 这里的正确答案是什么?画布应该返回预期的颜色,还是返回实际的颜色(所以我们必须整天在这里回答关于“为什么我把黑色的这个像素测量为深红色?”的问题)。

有些人会争辩说 Firefox 在这里做错了。

【讨论】:

    【解决方案3】:

    这是一种对任何画布内容(文本、图像、矢量等)进行亚像素渲染的方法。 http://johnvalentine.co.uk/subpixel-html5-canvas.htm.

    方法概要

    它在画布上绘制,然后将其绘制到屏幕上以利用 RGB 条带子像素。它也适用于 Alpha 通道。请注意,如果您使用的是纵向显示、非条纹像素,或者如果您的浏览器以比您的显示器更低的分辨率显示画布,这可能不起作用。

    有微调的余地,但对于一个简单的方法来说,这是一个很大的收获。它适用于我测试过的所有浏览器,但仅适用于画布与屏幕像素比为 1:1 的情况(但我相信已经为此提供了解决方案)。

    【讨论】:

    • 有趣的方法,对于一次性图形生成来说,这是一个不错的主意。但是对于任何类型的动画,它都会非常缓慢并且完全无法使用:(
    • @zyklus,这取决于你如何渲染它。而不是重新渲染整个图像,只将动画第一帧不同的部分重新渲染到第二帧。
    【解决方案4】:

    这是可能的,具体取决于平台。操作方法如下:

    1. 创建一个不透明的画布上下文,使用canvas.getContext('2d', {alpha: false})
    2. -webkit-font-smoothing 属性设置为所需的值:autoantialias(模糊)、subpixel-antialias(带有彩色边缘的“LCD”文本)或none

    这将应用于画布中的所有文本。

    这是 Mac 上 Chrome 81 的屏幕截图;绿色矩形中的文字是画布fillText:

    这里是这个文件的来源:

    
    <!DOCTYPE html>
    <style>
    canvas {
      border: 1px solid green;
    }
    div {
      position: float;
      float: left;
    }
    #a {
      -webkit-font-smoothing: auto;
    }
    #b {
      -webkit-font-smoothing: antialiased;
    }
    #c {
      -webkit-font-smoothing: subpixel-antialiased;
    }
    #d {
      -webkit-font-smoothing: none;
    }
    </style>
    <div id="a">
    (auto)<br>
    ??????????<br>
    ||||||||||<br>
    IIIIIIIIII<br>
    llllllllll<br>
    //////////<br>
    </div>
    <div id="b">
    (antialiased)<br>
    ??????????<br>
    ||||||||||<br>
    IIIIIIIIII<br>
    llllllllll<br>
    //////////<br>
    </div>
    <div id="c">
    (subpixel)<br>
    ??????????<br>
    ||||||||||<br>
    IIIIIIIIII<br>
    llllllllll<br>
    //////////<br>
    </div>
    <div id="d">
    (none)<br>
    ??????????<br>
    ||||||||||<br>
    IIIIIIIIII<br>
    llllllllll<br>
    //////////<br>
    </div>
    <script>
    'use strict';
    function add(container) {
      let canvas = document.createElement('canvas');
      const width = container.clientWidth;
      canvas.style.width = `${width}px`;
      const height = 40;
      canvas.style.height = `${height}px`;
      canvas.width = Math.floor(width * window.devicePixelRatio);
      canvas.height = Math.floor(height * window.devicePixelRatio);
      container.append(canvas);
      let ctx = canvas.getContext('2d', {alpha: false});
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = 'black';
      ctx.font = '12pt Arial';
      ctx.fillText('\/!|hello world', 0, height / 2);
    }
    
    add(a);
    add(b);
    add(c);
    add(d);
    </script>
    

    【讨论】:

    • 你正在回答一个 9 年前的问题......当被问到时这是不可能的
    • 是的...但是这个问题仍然是相关的,所以我想我会为下一个搜索它的人回答这个问题。
    猜你喜欢
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 2015-09-14
    • 2011-08-02
    • 2012-09-21
    • 2012-04-22
    相关资源
    最近更新 更多