d3.js - 为什么笔画模糊除非偏移 0.5?

d3.js - why are strokes blurry unless offset by 0.5?

我正在尝试使用 d3 构建仪表板,并将我的布局构建为响应式网格。我正在使用 d3 向我的网格中的每个项目添加一个 svg 元素,当我添加 svg 元素时,我还添加了一个相对于每个网格项目的大小定位和缩放的矩形。 rect的笔画(stroke-width=1)总是画得很模糊,唯一的办法就是给rect的x和y位置加0.5。

模糊:

Crisp(矩形偏移 0.5):

我了解什么是抗锯齿以及它是如何从根本上导致线条模糊的。我试图了解 how/where/why 矩形被放置 0.5 关闭,或者如果默认情况下它们被放置在像素之间。

我正在使用 .clientHeight/.clientWidth 来设置 svg 元素的视图框,以及设置矩形的大小。这两个变量 return 整数。我正在使用 'fr' 单位来定义网格,我尝试切换到绝对像素值,但没有帮助。

非常感谢,这里有一个片段和一个 codepen 项目:

  let rect = svg.selectAll('rect').data([null]);
  rect.enter().append('rect')
    .merge(rect)
      .attr('x', 10) // if I make these values '10.5'
      .attr('y', 10) // then everything looks crisp...
      .attr('width', props.width - 20)
      .attr('height', props.height - 20)
      .style('fill', 'none')
      .style('stroke', '#FFFFFF')
      .style('stroke-width', '1')

https://codepen.io/markersniffen/project/editor/AKmYea

这是因为在 SVG(以及 HTML5 的 <canvas>)中,每个 "pixel" 坐标点都存在于 介于 像素之间的直线上.

因此,如果您有一条从 (0,0)(0,5) 的 1px 宽的垂直线,那么如果该线的笔划被转换为矩形,则其坐标将是:

(插图未按比例绘制):

   (-0.5, -0.5)  +-------+  (0.5, -0.5)
                 |       |
                 |       |
                 |       |
                 |       |
                 |<-1px->|
                 |       |
                 |       |
                 |       |
                 |       |
   (-0.5,  5.5)  +-------+  (0.5,  5.5)

如您所见,通过将您自己的 0.5px 偏移应用到点坐标,然后线条再次捕捉到像素网格:

         (0, 0)  +-------+  (1, 0)
                 |       |
                 |       |
                 |       |
                 |       |
                 |<-1px->|
                 |       |
                 |       |
                 |       |
                 |       |
         (0, 6)  +-------+  (1, 6)

要纠正此问题(无双关语意),您可以继续使用 +0.5px 偏移方法,或确保像素对齐线的所有笔划都是 2px 宽度的倍数(但这确实意味着你不能有 1px 宽的描边线或沿着整数像素坐标点的路径。

您还可以更改每个 SVG path/shape 元素的抗锯齿设置,但我不推荐这样做,因为如果您有任何笔划或点未与像素网格完全对齐 (即您的 SVG 文件不仅仅是水平和垂直线)那么结果在屏幕上看起来会很难看,尤其是在低 DPI 设备上。