在画布上渲染灰色文本看起来很糟糕

时间:2016-10-25 01:53:28

标签: javascript canvas text-rendering

为什么将灰色文本渲染到画布上看起来非常糟糕?在我的例子中,第一段文字看起来很棒,第二块看起来很糟糕,第三块看起来很难看。

以下是我看到的截图:

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>
&#13;
&#13;
&#13;

在标记为重复之前,请注意我已经在StackOverflow和Google上搜索过,并且由于以下原因,答案不足:   - 我没有使用视网膜监视器 - 我的像素比率是1,所以事实并非如此    关于使用更大的画布尺寸。   - 我尝试在&#34;半像素&#34;上渲染字体,但这并没有改变任何东西。在半像素上渲染有助于线条之类的东西,但不是文字。

1 个答案:

答案 0 :(得分:1)

糟糕的文字渲染修复

哦,你找到了神奇的颜色组合。把它放在很长的画布问题清单上。

注意我只在Chrome上发现此问题,Firefox没有问题。我不能使用Edge因为某些原因它会加热我的笔记本电脑导致关机。所以不了解Edge。

原因是因为画布是透明的,标准表示完全透明的像素必须是alpha倍增,使它们变黑(这是为了阻止哑图像编码器编码无法看到的透明颜色信息)。渲染器认为画布下的是黑色,因为这是透明像素的颜色。

如何解决。

有三种解决方案,即第二种解决方案不起作用的nope scratch。

我能想到的解决方案涉及的代码少于100行。

首先绘制背景,然后在

上绘制文本

我认为第二个解决方案只是绘制一个非常低的alpha值的轮廓。但是仍然会发现糟糕的预乘透明黑色

第三个是用文本颜色填充(fillRect)画布,然后将comp模式设置为&#34; destination-in&#34;并绘制文本。这允许您在文本

下仍然具有透明像素

显示代码的代码段。

&#13;
&#13;
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";
&#13;
div {
  font-family: "arial";
  font-size: 12px;
  color: #bbbbbb;
  background : #f3f5f6;
}
&#13;
<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>
&#13;
&#13;
&#13;