在 canvas 上呈现灰色文本看起来很糟糕
Rendering gray text on canvas looks awful
为什么在 canvas 上呈现灰色文本看起来非常糟糕?在我的示例中,第一段文字看起来不错,第二段看起来很糟糕,第三段看起来还过得去。
这是我看到的截图:
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>
在标记为重复之前,请注意我已经在 Whosebug 和 Google 上进行了搜索,但由于以下原因,那里的答案不足:
- 我没有使用视网膜显示器——我的像素比是 1,所以这不是
关于使用更大的 canvas 尺寸。
- 我试过在 "half pixel" 上渲染字体,但这并没有改变任何东西。在半像素上渲染有助于线条之类的东西,但对文本没有帮助。
糟糕的文本渲染修复
哦,你找到了神奇的颜色组合。把它记在一长串 canvas 个问题中。
注意我只在 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>
为什么在 canvas 上呈现灰色文本看起来非常糟糕?在我的示例中,第一段文字看起来不错,第二段看起来很糟糕,第三段看起来还过得去。
这是我看到的截图:
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>
在标记为重复之前,请注意我已经在 Whosebug 和 Google 上进行了搜索,但由于以下原因,那里的答案不足: - 我没有使用视网膜显示器——我的像素比是 1,所以这不是 关于使用更大的 canvas 尺寸。 - 我试过在 "half pixel" 上渲染字体,但这并没有改变任何东西。在半像素上渲染有助于线条之类的东西,但对文本没有帮助。
糟糕的文本渲染修复
哦,你找到了神奇的颜色组合。把它记在一长串 canvas 个问题中。
注意我只在 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>