出现奇怪的痕迹,当绘制带有锐角的字母形状的轮廓时。如何避免它们?

huangapple go评论72阅读模式
英文:

Strange artifacts appear when drawing outlines of letter shapes with sharp corners. How to avoid them?

问题

我目前正在使用HTML5的canvas来使用Impact字体渲染字符串。这个工作正常,但描边似乎超出了整个文本区域。有没有办法修复这个问题?

代码和渲染可以在这里查看:http://jsfiddle.net/5uczpa1k/

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.font = "80px Impact";
ctx.strokeStyle = 'black';
ctx.lineWidth = 20;
ctx.fillStyle = 'white';
ctx.strokeText("A TEXT DEMO", 50, 150);
ctx.fillText("A TEXT DEMO", 50, 150);
<canvas id="myCanvas" width="500" height="500"></canvas>
英文:

I'm currently using HTML5's canvas to render a string using the Impact font. This works fine, but the stroke appears to be bleeding out of the whole text area. Is there any way to fix this?

Code and render can be seen here: http://jsfiddle.net/5uczpa1k/

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var c = document.getElementById(&quot;myCanvas&quot;);
var ctx = c.getContext(&quot;2d&quot;);

ctx.font = &quot;80px Impact&quot;;
ctx.strokeStyle = &#39;black&#39;;
ctx.lineWidth = 20;
ctx.fillStyle = &#39;white&#39;;
ctx.strokeText(&quot;A TEXT DEMO&quot;, 50, 150);
ctx.fillText(&quot;A TEXT DEMO&quot;, 50, 150);

<!-- language: lang-html -->

&lt;canvas id=&quot;myCanvas&quot; width=&quot;500&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

答案1

得分: 5

尝试添加一个 miterLimit - 这定义了线段连接处尖角长度与线段宽度之比的限制。当超过此限制时,连接从尖角转换为斜角:

<!-- 开始代码片段:js 隐藏:false 控制台:true Babel:false -->

<!-- 语言:lang-js -->
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.font = "80px Impact";
ctx.strokeStyle = 'black';
ctx.lineWidth = 20;
ctx.fillStyle = 'white';
ctx.miterLimit = 2;
ctx.strokeText("A TEXT DEMO", 50, 150);
ctx.fillText("A TEXT DEMO", 50, 150);

<!-- 语言:lang-html -->
<canvas id="myCanvas" width="500" height="500"></canvas>

<!-- 结束代码片段 -->

只翻译代码部分,不包括注释。

英文:

Try adding a miterLimit - this defines a limit on the ratio of the miter (corner) length to the stroke-width used to draw a miter join. When the limit is exceeded, the join is converted from a miter to a bevel:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var c = document.getElementById(&quot;myCanvas&quot;);
var ctx = c.getContext(&quot;2d&quot;);

ctx.font = &quot;80px Impact&quot;;
ctx.strokeStyle = &#39;black&#39;;
ctx.lineWidth = 20;
ctx.fillStyle = &#39;white&#39;;
ctx.miterLimit = 2;
ctx.strokeText(&quot;A TEXT DEMO&quot;, 50, 150);
ctx.fillText(&quot;A TEXT DEMO&quot;, 50, 150);

<!-- language: lang-html -->

&lt;canvas id=&quot;myCanvas&quot; width=&quot;500&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

答案2

得分: -1

ctx.lineJoin = 'bevel';

描边始终是内外各占一半,除非您自行进行必要的计算并绘制两个单独的形状,一个用于填充,一个用于轮廓。即使线宽是奇数,也会应用默认的半内半外方法,此时浏览器会尝试在两个实际像素之间绘制一半,导致模糊和颜色强度丧失(除非您通过应用平移变换在两个维度上都移动0.5px来将画布移动0.5px)。当涉及半透明度时,这更成为问题。描边之后执行了不透明的填充。因此,净效果是您的轮廓实际上变成了“外部”,但其表观宽度是代码中声明的宽度的一半。

英文:
ctx.lineJoin = &#39;bevel&#39;;

The stroke is always drawn half inside and half outside, unless you make the necessary calculations to do something different yourself and draw two separate shapes, one for the fill and one for the outline. The default half-and-half approach is applied even when the lineWidth is an odd number, in which case the browser will attempt to draw halfway between two actual pixels, resulting in blurring and loss of colour intensity (unless you shift the canvas by 0.5px in both dimensions by applying a translation transform). This is more of a problem when translucency is involved. You have an opaque fill being performed after the stroke. So the net effect is that your outline effectively becomes "outside" but its apparent width is half of the width stated in the code.

huangapple
  • 本文由 发表于 2023年5月13日 22:52:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76243335.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定