Html HTML5 画布元素上的亚像素抗锯齿文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4550926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 05:53:19  来源:igfitidea点击:

Subpixel anti-aliased text on HTML5's canvas element

htmltextcanvasantialiasingsubpixel

提问by Matt Mazur

I'm a bit confused with the way the canvas element anti-aliases text and am hoping you all can help.

我对画布元素抗锯齿文本的方式有些困惑,希望大家能提供帮助。

In the following screenshot the top "Quick Brown Fox" is an H1 element and the bottom one is a canvas element with text rendered on it. On the bottom you can see both "F"s placed side by side and zoomed in. Notice how the H1 element blends better with the background:

在下面的屏幕截图中,顶部的“Quick Brown Fox”是一个 H1 元素,底部的一个是带有渲染文本的画布元素。在底部,您可以看到并排放置并放大的两个“F”。请注意 H1 元素如何与背景更好地融合:

Here's the code I'm using to render the canvas text:

这是我用来呈现画布文本的代码:

        var canvas = document.getElementById('canvas');
        if (canvas.getContext){

            var ctx = canvas.getContext('2d');
            ctx.fillStyle = 'black';
            ctx.font = '26px Arial';
            ctx.fillText('Quick Brown Fox', 0, 26);
        }

Is it possible to render the text on the canvas in a way so that it looks identical to the H1 element? And why are they different?

是否可以以某种方式在画布上呈现文本,使其看起来与 H1 元素相同?为什么它们不同?

采纳答案by Matt Mazur

Answering my own question:

回答我自己的问题:

It is possible using the technique demonstrated on this site:

可以使用本网站上展示的技术:

https://bel.fi/alankila/lcd/

https://bel.fi/alankila/lcd/

The only problem is that its too slow to implement in a production app. If anyone runs across a faster way please let me know.

唯一的问题是在生产应用程序中实现它太慢了。如果有人跑过更快的方式,请告诉我。

回答by sirwart

It's now possible to get sub-pixel font rendering by creating an opaque canvas context. In Safari and Chrome you can get this using this snippet:

现在可以通过创建一个不透明的画布上下文来获得亚像素字体渲染。在 Safari 和 Chrome 中,您可以使用以下代码段获取此信息:

var ctx = canvas.getContext("2d", {alpha: false})

var ctx = canvas.getContext("2d", {alpha: false})

I found this from this blog post.

我从这篇博客文章中找到了这个。

回答by Joubert Nel

Matt, I sat with the (same/similar) problem last week, which, in my case, turned out to be because of differences in pixel densities on the devices I was testing; I wrote about it tonight - http://joubert.posterous.com/crisp-html-5-canvas-text-on-mobile-phones-and

马特,上周我遇到了(相同/相似的)问题,就我而言,这是因为我正在测试的设备上的像素密度不同;我今晚写了这篇文章 - http://joubert.posterous.com/crisp-html-5-canvas-text-on-mobile-phones-and

The link at posterous is dead, so here is the gist with the source code: https://gist.github.com/joubertnel/870190

海报上的链接已经死了,所以这里是源代码的要点:https://gist.github.com/joubertnel/870190

And the snippet itself:

和片段本身:

  // Output to Canvas without consideration of device pixel ratio
  var naiveContext = $('#naive')[0].getContext('2d');    
  naiveContext.font = '16px Palatino';
  naiveContext.fillText('Rothko is classified as an abstract expressionist.', 10, 20);

  // Output to Canvas, taking into account devices such as iPhone 4 with Retina Display
  var hidefCanvas = $('#hidef')[0];
  var hidefContext = hidefCanvas.getContext('2d');

  if (window.devicePixelRatio) {
    var hidefCanvasWidth = $(hidefCanvas).attr('width');
    var hidefCanvasHeight = $(hidefCanvas).attr('height');
    var hidefCanvasCssWidth = hidefCanvasWidth;
    var hidefCanvasCssHeight = hidefCanvasHeight;

    $(hidefCanvas).attr('width', hidefCanvasWidth * window.devicePixelRatio);
    $(hidefCanvas).attr('height', hidefCanvasHeight * window.devicePixelRatio);
    $(hidefCanvas).css('width', hidefCanvasCssWidth);
    $(hidefCanvas).css('height', hidefCanvasCssHeight);
    hidefContext.scale(window.devicePixelRatio, window.devicePixelRatio);               
  }

  hidefContext.font = "16px Palantino";
  hidefContext.fillText("Rothko is classified as an abstract expressionist.", 10, 20);

回答by j5v

Here's a way of doing sub-pixel rendering for anycanvas content (text, images, vectors, etc). http://johnvalentine.co.uk/archive.php?art=tft.

这是对任何画布内容(文本、图像、矢量等)进行子像素渲染的方法。http://johnvalentine.co.uk/archive.php?art=tft

Outline of the method

It draws onto a canvas, which is then drawn to the screen to take advantage of RGB-striped subpixels. It works with alpha channels too. Note that this might not work if you are using a portrait display, non-striped pixels, or if your browser displays canvases at a lower resolution than your display.

方法概要

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

There's scope for fine-tuning, but it's a big gain for a simple method.

有微调的余地,但对于一个简单的方法来说,这是一个很大的收获。

回答by Phrogz

This is generically called subpixel anti-aliasing, or ClearTypeon Windows. I'm not aware of any OS/browser combinations that currently support this for Canvas.

这在 Windows 上通常称为子像素抗锯齿ClearType。我不知道当前支持 Canvas 的任何操作系统/浏览器组合。

I'd be interested to see some tests using sub-pixel offsets for the text to see if any browsers even use pixel-based hinting of the font rendering (aligning ascenders on pixel boundaries, for example). My assumption would be no.

我很想看到一些对文本使用子像素偏移的测试,以查看是否有任何浏览器甚至使用基于像素的字体渲染提示(例如,在像素边界上对齐上升部分)。我的假设是否定的。

Edit: My assumption was wrong; it would appear that Safari, Chrome, and Firefox all utilize some pixel font hinting. Safari and Chrome appear the same, snapping to whole pixel boundaries, but are different from Firefox (snapping to half-pixel boundaries?). See the visual results of testing (on OS X) here: http://phrogz.net/tmp/canvas_text_subpixel.html

编辑:我的假设是错误的;Safari、Chrome 和 Firefox 似乎都使用了一些像素字体提示。Safari 和 Chrome 看起来相同,捕捉到整个像素边界,但与 Firefox 不同(捕捉到半像素边界?)。在此处查看测试的视觉结果(在 OS X 上):http: //phrogz.net/tmp/canvas_text_subpixel.html