如何在 d3.js 中制作带有圆角和扩展网格的条形图?

Kun*_*ist 3 javascript charts d3.js

我正在尝试使用 D3.js 创建一个条形图。条件是 Bar 应该具有固定的宽度和条形之间的填充,并且它应该绘制在网格线的中心。

工具提示应该在点击时出现一条垂直线

我能够创建带有绘制条的网格线,不知何故 rx,ry 从两侧四舍五入。我怎样才能达到同样的结果。

var rectCluster = svg.selectAll(".bar")
                    .data(data);

                rectCluster
                    .enter().append("rect")
                    .attr("class", function(d) {
                        return "bar";
                    })
                    .attr(attrs)
                    .attr({ry : (20), rx : 20 })
                    .attr("x", function(d) { return x(d.text); })
                    .attr("y", function(d) {
                        return height;
                    })
                    .style("fill", function(d) {
                        return color(d.text);
                    })
                    .attr("width", x.rangeBand())
                    .attr("height", 0)
                    .transition()
                    .duration(animationDelay)
                    .delay(function(d, i) {
                        return i * animationDelay;
                    })
                    .attr("y", function(d) { return y(d.score); })
                    .attr("height", function(d) { return height - y(d.score) });

                    var attrs = {
    width: function(d, i){
      return o.rangeBand();
    },
    height: function(d, i){
      return yScale(d);
    },
    fill: "#384252",
    x: function(d, i){
      return xScale(i);
    },
    y: function(d, i){
      return height - yScale(d) - margin.bottom;
    }
  };
Run Code Online (Sandbox Code Playgroud)

Js Fiddle 相同

我正在努力实现这样的目标。在此处输入图片说明

And*_*eid 10

一种选择是使用剪切路径,但您也可以使用用于构建矩形的相同信息创建一个简单的路径生成器:x、y、宽度、高度和半径。路径相当简单:

  1. 移动到左下角
  2. 线到左上弧线的底部
  3. 弧到左上弧的顶部
  4. 线到右上角圆弧的顶部
  5. 圆弧到右上方圆弧的底部。
  6. 线到右下角
  7. 关闭路径。

这是一起出现的东西:

  1. M x,y
  2. L x,y-高度+半径
  3. 半径,radius,0,0,1,x+radius,y-height
  4. L x+宽-r,y-高
  5. 半径,radius,0,0,1,x+width,y-height+radius
  6. 长 x+宽,y
  7. Z

看起来像这样(一个相当懒惰的实现):

function bar(x,y,w,h,r,f) {
    // Flag for sweep:
    if(f == undefined) f = 1;
    // x coordinates of top of arcs
    var x0 = x+r;
    var x1 = x+w-r;
    // y coordinates of bottom of arcs
    var y0 = y-h+r;

    // assemble path:
    var parts = [
      "M",x,y,               // step 1
      "L",x,y0,              // step 2
      "A",r,r,0,0,f,x0,y-h,  // step 3
      "L",x1,y-h,            // step 4
      "A",r,r,0,0,f,x+w,y0,  // step 5
      "L",x+w,y,             // step 6
      "Z"                    // step 7
     ];
    return parts.join(" ");
}
Run Code Online (Sandbox Code Playgroud)

我已经包含了一个可选的扫描标志 ( f) - 如果设置为 0,它将反转弧线。

并应用了这样的东西:

 .attr("d", function(d) { 
    return bar(x(d),y(0),x.bandwidth(),y(0)-y(d),15);  
  })
Run Code Online (Sandbox Code Playgroud)

放在一起你可能会得到类似的东西:

function bar(x,y,w,h,r,f) {
    // Flag for sweep:
    if(f == undefined) f = 1;
    // x coordinates of top of arcs
    var x0 = x+r;
    var x1 = x+w-r;
    // y coordinates of bottom of arcs
    var y0 = y-h+r;

    // assemble path:
    var parts = [
      "M",x,y,               // step 1
      "L",x,y0,              // step 2
      "A",r,r,0,0,f,x0,y-h,  // step 3
      "L",x1,y-h,            // step 4
      "A",r,r,0,0,f,x+w,y0,  // step 5
      "L",x+w,y,             // step 6
      "Z"                    // step 7
     ];
    return parts.join(" ");
}
Run Code Online (Sandbox Code Playgroud)
 .attr("d", function(d) { 
    return bar(x(d),y(0),x.bandwidth(),y(0)-y(d),15);  
  })
Run Code Online (Sandbox Code Playgroud)

如果你的半径超过半条高度或宽度,你会得到一些更有趣的结果,一个完整的实现会考虑检查以确保条的半径不会太大