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')
这是因为在 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 设备上。
我正在尝试使用 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')
这是因为在 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 设备上。