【问题标题】:JavaScript either strokeRect or fillRect blurry depending on translationJavaScript 的 strokeRect 或 fillRect 模糊取决于翻译
【发布时间】:2015-03-19 10:06:41
【问题描述】:

早些时候我注意到strokeRect(以及任何其他涉及笔划的方法,例如lineTo)创建了一条2 px 宽的灰色线条,而不是1 px 宽的黑色线条。经过一些谷歌搜索后,我发现context.translate(0.5, 0.5) 解决了这个问题。但是现在fillRect(和之前涉及fill 的任何其他方法一样)创建了一个带有灰色边框的黑框。

有没有人知道一个好方法来使 fillRect 和 strokeRect 都具有清晰的边缘而没有灰色边框?我也不知道是否应该对图像使用context.translate(0.5, 0.5),因为无论我是否翻译,SVG 似乎都有清晰的边缘。

这是一个演示这个的 jsfiddle:http://jsfiddle.net/Tysonzero/ydm21pkt/1/

请注意,底部的strokeRect清晰而顶部的模糊,顶部的fillRect清晰而底部的模糊。

【问题讨论】:

  • 它们绝对是整数。我一般使用(100, 100, 100, 100) 或类似的。
  • 您的实际画布尺寸是否在 css 中缩放?
  • 什么意思?我不直接在 CSS 中设置画布大小,而是在 JavaScript 中设置宽度和高度,它会自动重新调整大小。我可以向你保证,这些都不是问题。 Here 就是我所说的那种东西。

标签: javascript html canvas


【解决方案1】:

笔画在 x,y 坐标的一半内侧和一半外侧绘制。这就是为什么您会看到整数 x,y 的模糊以及为什么当 x,y 偏移半个像素时它会清除的原因。以下是关于为什么会出现模糊的更多信息:http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/

使矩形更清晰的一种简单方法是向上下文实例添加方法,以抵消 strokeRect 和 fillRect 以获得最佳外观:

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

// add pixel aligned versions of strokeRect & fillRect to this context instance
context.sRect=function(x,y,w,h){
  x=parseInt(x)+0.50;
  y=parseInt(y)+0.50;
  this.strokeRect(x,y,w,h);
}
context.fRect=function(x,y,w,h){
  x=parseInt(x);
  y=parseInt(y);
  context.fillRect(x,y,w,h);
}

context.strokeStyle = "#000000";
context.fillStyle = "#000000";

context.strokeRect(100, 50, 100, 100);
context.fillRect(300.5, 50.5, 100, 100);


context.sRect(100,200,100,100);
context.fRect(300.5,200,100,100);

context.fillText('Unadjusted',20,100);
context.fillText('Adjusted',20,250);
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=500 height=500></canvas>

【讨论】:

  • 有道理,谢谢!我确实有一个问题是为什么您在 fRect 示例中使用 300.5,fRect 的重点不是避免使用浮点数吗?最后我意识到它被解析为 300,但我只是觉得这有点奇怪。如果给定相同的坐标,这些确切的功能是否可以使sRects 和fRects 的外部完美对齐?在某些情况下,这可能对审美吸引力非常重要。
  • 不客气! 300.5 就是这样问题才会发生,所以我可以测试它是否被 fRect 治愈;-) 我使用 parseInt (而不是四舍五入),所以所有的调整都会被拉到左边。这提供了完美对齐的最佳镜头。但对齐并不总是完美的。最后一个添加可能是一种方法,它首先填充一个矩形,然后还描边同一个矩形。在这种情况下,将让填充在所有 4 个面上流血 0.50 像素。立即中风将覆盖任何出血。这允许完美填充+描边的矩形。祝你的项目好运!
  • 谢谢你!我真的很喜欢 JS / Canvas,即使 JS 很古怪。我想我会采用您刚才建议的方法,将所有对象转换为 0.5,并对填充的矩形使用描边和填充,但对未填充的矩形只使用描边。
  • 是的,有点违反直觉 ctx.strokeRect() 和 ctx.fillRect() 在这方面有相反的行为。我也花了一些时间才弄清楚!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 2021-04-01
  • 2010-11-25
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多