javascript - 在 Canvas 上呈现灰色文本看起来很糟糕

标签 javascript canvas text-rendering

为什么在 Canvas 上渲染灰色文本看起来非常糟糕?在我的例子中,第一段文字看起来不错,第二段看起来很糟糕,第三段看起来还过得去。

这是我看到的截图:

Screenshot

var g = document.getElementById('canvas').getContext('2d');

g.font = "12px arial";

g.fillStyle = "#bbbbbb";
g.fillText("This is some example text. (CANVAS, gray)", 0, 30);

g.fillStyle = "black";
g.fillText("This is some example text. (CANVAS, black)", 0, 60);
div {
  font-family: "arial";
  font-size: 12px;
  color: #bbbbbb;
}
<div>This is some example text. (DOM, gray)</div>
<canvas id="canvas" width="377" height="174"></canvas>


在标记为重复之前,请注意我已经在 StackOverflow 和 Google 上进行了搜索,但由于以下原因,那里的答案不足: - 我没有使用视网膜显示器——我的像素比是 1,所以这不是 关于使用更大的 Canvas 尺寸。 - 我试过在“半像素”上渲染字体,但这并没有改变任何东西。在半像素上渲染有助于线条之类的东西,但对文本没有帮助。

最佳答案

糟糕的文本渲染修复

哦,你找到了神奇的颜色组合。把它记在长长的 Canvas 问题 list 上。

注意我只在 Chrome 上发现了这个问题,Firefox 没有问题。我无法使用 Edge,因为它会使我的笔记本电脑过热而导致关机。所以不了解 Edge。

原因是因为 Canvas 是透明的,标准规定完全透明的像素必须进行 alpha 乘法运算才能使它们变黑(这是为了阻止哑图像编码器编码看不见的透明颜色信息)。渲染器认为 Canvas 下面是黑色,因为那是透明像素的颜色。

如何修复。

一共有三种解决方案,第二个解决方案行不通。

我能想到两个不到 100 行代码的解决方案。

先画背景,再在上面画文字

我认为的第二个解决方案是用非常低的 alpha 值绘制轮廓。但这仍然会拾取不好的预乘透明黑色

第三种是用文本颜色填充(fillRect) Canvas ,然后将comp模式设置为“destination-in”并绘制文本。这允许您在文本下方仍然有透明像素

显示代码的片段。

var g = document.getElementById('canvas').getContext('2d');
g.font = "12px arial";
g.fillStyle = "#bbbbbb";
g.fillText("Very bad text rendering", 0, 12);

var g = document.getElementById('canvas1').getContext('2d');
g.font = "12px arial";
g.fillStyle = "#f3f5f6" 
g.fillRect(0,0,g.canvas.width,g.canvas.height);
g.fillStyle = "#bbbbbb";
g.fillText("Fixed with solid background", 0, 12);

var g = document.getElementById('canvas2').getContext('2d');
g.font = "12px arial";
g.strokeStyle = "rgba("+0xf3+","+0xf5+","+0xf6+",0.05)"; 
g.lineWidth = 2;
g.lineJoin = "round";
g.strokeText("Tried with pixel outline", 0, 12);
g.fillStyle = "#bbbbbb";
g.fillText("Tried with pixel outline", 0, 12);

var g = document.getElementById('canvas3').getContext('2d');
g.font = "12px arial";
g.fillStyle = "#bbbbbb";
g.fillRect(0,0,g.canvas.width,g.canvas.height);
g.globalCompositeOperation = "destination-in";
g.fillText("Fixed with comp op destination-in on text colour", 0, 12);
g.globalCompositeOperation = "source-over";
div {
  font-family: "arial";
  font-size: 12px;
  color: #bbbbbb;
  background : #f3f5f6;
}
<div>This is some example text. (DOM, gray)<br>
<canvas id="canvas" width="377" height="18"></canvas>
<canvas id="canvas1" width="377" height="18"></canvas>
<canvas id="canvas2" width="377" height="18"></canvas>
<canvas id="canvas3" width="377" height="18"></canvas>
</div>

关于javascript - 在 Canvas 上呈现灰色文本看起来很糟糕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40230166/

相关文章:

javascript - AngularJS ng-show 无法使用我在工厂中定义的函数

javascript - 如何将 icomoon 图标添加到 Canvas ?

JavaFX - 将 Canvas 保存到 png 文件

c++ - 硬件加速 Unicode 文本渲染

java - 无法切换到主窗口内的浏览器窗口。(Selenium Webdriver)

javascript不会拼接数组的所有元素

lazarus - 如何更改 Delphi TStringGrid 中固定行单元格中的文本方向

WPF TextFormattingOptions.Display 更改字母间距

javascript - 为什么 Firebase 事件 'child_added' 在 'value' 事件之后触发?

javascript - 如何使用 CSS 设置 Canvas 元素的样式