svg / d3.js 矩形一个角上的圆角
Posted
技术标签:
【中文标题】svg / d3.js 矩形一个角上的圆角【英文标题】:svg / d3.js rounded corners on one side of a rectangle 【发布时间】:2012-08-20 09:20:32 【问题描述】:我知道 svg 有一个内置函数来做圆角,但我只需要在四个角中的两个上做圆角。
我知道我可以在彼此的顶部绘制多个矩形来模仿它,但这似乎有点俗气。有什么方法可以使用剪辑或任何 d3.js 方法来做到这一点?
现在我有一个水平条形图,其矩形如下:
rects.enter().append("rect")
.attr("x",function(d,i) return x(0); )
.attr("width",function(d) return x(d.value) - x(0); )
.attr("height",y.rangeBand())
.attr("y",function(d) return y(d.name); )
我正在尝试在矩形的右侧制作圆角,但不知道该怎么做。
【问题讨论】:
【参考方案1】:扩展@robert-longson 的答案,您可以使用 SVG 的 elliptical arc commands 制作角,并结合 lineto commands 制作直边。这些与path elements 一起使用。这是一种可能的实现方式:
// Returns path data for a rectangle with rounded right corners.
// The top-left corner is ⟨x,y⟩.
function rightRoundedRect(x, y, width, height, radius)
return "M" + x + "," + y
+ "h" + (width - radius)
+ "a" + radius + "," + radius + " 0 0 1 " + radius + "," + radius
+ "v" + (height - 2 * radius)
+ "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + radius
+ "h" + (radius - width)
+ "z";
然后您可以调用此函数来计算“d”属性。例如:
rects.enter().append("path")
.attr("d", function(d)
return rightRoundedRect(x(0), y(d.name), x(d.value) - x(0), y.rangeBand(), 10);
);
活生生的例子:
http://bl.ocks.org/3468167可选:如果您愿意,可以重构 rightRoundedRect 函数以使其可配置,而不是使用大量参数。这种方法类似于 D3 的内置shape generators。例如,您可能会像这样使用 rect 生成器:
rects.enter().append("path")
.attr("d", rightRoundedRect()
.x(x(0))
.y(function(d) return y(d.name); )
.width(function(d) return x(d.value) - x(0); )
.height(y.rangeBand())
.radius(10));
有关该方法的更多详细信息,请参阅configurable function tutorial。
【讨论】:
@mbostock:我相信你遗漏了半径参数。我已经为你添加了。感谢您提供了一个很棒的答案/库! 在做.attr
时,'x'和'y'变量从何而来?例如x(0)
和 y(d.name)
Nvm,意识到他们只是引用任意现有数据【参考方案2】:
只是为了扩展给出的答案,这里有一个更全面的函数来返回你的矩形路径。
x: x-coordinate
y: y-coordinate
w: width
h: height
r: corner radius
tl: top_left rounded?
tr: top_right rounded?
bl: bottom_left rounded?
br: bottom_right rounded?
function rounded_rect(x, y, w, h, r, tl, tr, bl, br)
var retval;
retval = "M" + (x + r) + "," + y;
retval += "h" + (w - 2*r);
if (tr) retval += "a" + r + "," + r + " 0 0 1 " + r + "," + r;
else retval += "h" + r; retval += "v" + r;
retval += "v" + (h - 2*r);
if (br) retval += "a" + r + "," + r + " 0 0 1 " + -r + "," + r;
else retval += "v" + r; retval += "h" + -r;
retval += "h" + (2*r - w);
if (bl) retval += "a" + r + "," + r + " 0 0 1 " + -r + "," + -r;
else retval += "h" + -r; retval += "v" + -r;
retval += "v" + (2*r - h);
if (tl) retval += "a" + r + "," + r + " 0 0 1 " + r + "," + -r;
else retval += "v" + -r; retval += "h" + r;
retval += "z";
return retval;
【讨论】:
@stackmate:如何在栏内添加图像或圆圈 我们能看到一个这样的例子吗? 非常好,可以灵活地使用半径打开的四个角中的任何一个。非常好,正是我所追求的。 优秀的解决方案!荣誉 你是救世主,谢谢【参考方案3】:如果其他人最终来到这里想要圆化 rect
元素的 所有 角,您可以将 rx
属性添加到 rect
元素(正如 @mbostock 在他的小提琴中提到的那样以上):
var rectangle = group.append("rect")
.attr("width", 60)
.attr("height", 75)
.attr("rx", 4)
.style("fill", function(d) return "#e6653e"; )
.style("stroke", function(d) return d3.rgb("#e6653e").darker(); )
【讨论】:
【参考方案4】:任何寻找 Eslinted 版本的 stackmate -s 答案的人:
function roundedRect(x, y, w, h, r, tl, tr, bl, br)
let retval;
retval = `M$x + r,$y`;
retval += `h$w - (2 * r)`;
if (tr)
retval += `a$r,$r 0 0 1 $r,$r`;
else
retval += `h$r`; retval += `v$r`;
retval += `v$h - (2 * r)`;
if (br)
retval += `a$r,$r 0 0 1 $-r,$r`;
else
retval += `v$r`; retval += `h$-r`;
retval += `h$(2 * r) - w`;
if (bl)
retval += `a$r,$r 0 0 1 $-r,$-r`;
else
retval += `h$-r`; retval += `v$-r`;
retval += `v$((2 * r) - h)`;
if (tl)
retval += `a$r,$r 0 0 1 $r,$-r`;
else
retval += `v$-r`; retval += `h$r`;
retval += 'z';
return retval;
【讨论】:
【参考方案5】:我最近发现自己遇到了这个问题,以便在 d3 中制作 顶部圆角的条形图。我对我找到的解决方案做了一个codesandbox demo。
【讨论】:
以上是关于svg / d3.js 矩形一个角上的圆角的主要内容,如果未能解决你的问题,请参考以下文章