【问题标题】:svg / d3.js rounded corners on one side of a rectanglesvg / d3.js 矩形一侧的圆角
【发布时间】:2012-08-24 19:44: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); })

我正在尝试在矩形的右侧制作圆角,但不知道该怎么做。

【问题讨论】:

    标签: javascript svg d3.js rounded-corners


    【解决方案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);
        });
    

    活生生的例子:

    可选:如果您愿意,可以重构 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

    【讨论】:

    • 出色的答案。为了舍入垂直条形图中的两个上角,我将rightRoundedRect 更改为这个,从(x,y+height) 开始:jsfiddle.net/wcyetoj7
    【解决方案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;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-08-20
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        • 1970-01-01
        • 2018-02-03
        • 2016-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多