带有半径、dasharray 和 dashoffset 的 svg 矩形

svg rectangle with radius, dash-array and dash-offset

我正在尝试使用半径 (rx, ry) 在 svg 中创建一个顶部和底部带有边框/描边并带有圆角的矩形。 通过使用 css 属性 "dasharray: width, height" 可以仅使用 border/stroke 设置顶部和底部的样式。没有半径,这会按预期工作。

但是,添加半径后,上边框不再从矩形的左上角开始。 我试图通过使用 css 属性 破折号偏移来纠正此行为,但这似乎使顶部边框部分消失(尽管它似乎适用于底部边框)。

非常感谢任何有关如何创建具有半径且只有顶部和底部边框的矩形的帮助,以及对正在发生的事情的一些见解。

查看 fiddle 位于:https://jsfiddle.net/Lus8ku7p/

<svg>
  <rect x =10 y=10 id=a ></rect>
  <rect x = 10 y=170 id=b class=round></rect>
  <rect x=170 y=10 id=c ></rect>
  <rect x=170 y=170 id=d class=round></rect>
</svg>
svg{
    width:400px;
    height:400px
}
rect {
   width: 150px;
   height: 150px;
   stroke-width:4px;
   stroke:black;
   fill:red;
   stroke-dasharray: 150 150;
}
.round{
   rx:20px;
   ry:20px;
 }
#c, #d{
   stroke-dashoffset: 40px;
 }

为了使虚线图案在所有 SVG 渲染器中呈现相同,SVG 规范定义了所有形状的虚线图案应从何处开始。 Including rectangles.

对于矩形,起点在矩形顶边的水平部分的左端。所以如果有圆角,它就在曲线与直线相交的地方。然后虚线图案沿顺时针方向绕矩形延伸。

该起点实际上是一条隧道或入口,破折号图案通过它出现和消失。你不能改变它的位置,你只需要在脑海中小心地构建你的破折号模式。

你没有说你想在顶部笔划中包含多少圆角,但我假设你想包含整个曲线。

在您的示例中,矩形为 150x150,角半径为 20。我们称它们为 w、h 和 r。

要正确计算虚线图案,我们需要准确计算出所有边和圆角的长度。

顶部和底部的长度均为 (w - 2 * r) = 110。让我们称之为 xlen.

左右边的长度为(w - 2 * r) = 110。我们称之为 ylen.

每个圆角的长度为 (PI * 2 * r) / 4 = 31.416。我们称之为 rlen

虚线图案版本 1

我们可以根据完成矩形周长所需的不同长度的图案来制作虚线图案。即

  • 矩形顶部(不包括左角):xlen + rlen = 141.416.
  • 图案右侧间隙:ylen = 110
  • 底边(包括两个角:rlen + xlen + rlen = 172.832.
  • 图案左侧间隙:ylen = 110
  • 左上角:rlen = 31.416.

所以破折号模式将是 "141.416 110 172.832 110 31.416"

rect {
  stroke-width: 4px;
  stroke: black;
  fill:red;
  stroke-dasharray: 141.416 110 172.832 110 31.416;
}
<svg width="400" height="400">
  <rect x="10" y="10" width="150" height="150" rx="20"/>
</svg>

虚线图案版本 2

另一个更简单但不太明显的解决方案可能是利用破折号模式重复这一事实。将其与破折号偏移相结合,我们可以使破折号图案更加简单。

  • 矩形顶部(包括两个角):rlen + xlen + rlen = 172.832.
  • 图案右侧间隙:ylen = 110
  • 然后让它重复形成底部和左侧。

所以破折号模式将是 "172.832 110"

"But wait" 您可能会说,这行不通,因为图案将顺时针移动一个圆角的长度。你是对的。

rect {
  stroke-width: 4px;
  stroke: black;
  fill:red;
  stroke-dasharray: 172.832 110;
}
<svg width="400" height="400">
  <rect x="10" y="10" width="150" height="150" rx="20"/>
</svg>

然而,如果我们使用 stroke-dashoffset 来移动模式 left/anti-clockwise,我们将丢失一些第一个破折号,但我们也会 "pulling" 一些下一个重复的通过 start/end "portal" 返回破折号图案。这依赖于破折号模式是完全正确的长度。这就是为什么我们一开始就非常小心地准确计算所有长度。

Spo 我们需要为 stroke-dashoffset 使用的值是多少?破折号偏移量的工作方式是它指定我们应该从多远的模式开始绘制。所以需要在圆角长度之后,或者31.416.

所以如果我们加上它我们得到:

rect {
  stroke-width: 4px;
  stroke: black;
  fill:red;
  stroke-dasharray: 172.832 110;
  stroke-dashoffset: 31.416;
}
<svg width="400" height="400">
  <rect x="10" y="10" width="150" height="150" rx="20"/>
</svg>

您可以看到,如果您希望破折号图案在正确的位置开始和停止,这是可能的。您只需要准确计算破折号图案的长度即可。

如果您需要在其他尺寸的矩形上使用相同类型的图案,您需要使用我在本答案开头列出的公式重新计算长度。