带有条形图的D3可缩放圆形包装(条形图缩放)

时间:2017-07-17 11:55:39

标签: javascript d3.js charts

我在D3中做过基本的事情,所以我对它没有深入的了解。 我用条形图创建了可缩放的圆形包装图。

以下是代码:

var xr, yr, xaxis, yaxis, bar, bg;
var svg = d3.select("svg"),
  margin = 20,
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom;
diameter = +svg.attr("width"),
  g = svg.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");


var color = d3.scaleLinear()
  .domain([-1, 5])
  .range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
  .interpolate(d3.interpolateHcl);

var pack = d3.pack()
  .size([diameter - margin, diameter - margin])
  .padding(2);

d3.json("occupation.json", function(error, root) {
  if (error) throw error;

  root = d3.hierarchy(root)
    .sum(function(d) {
      return d.size;
    })
    .sort(function(a, b) {
      return b.value - a.value;
    });

  var focus = root,
    nodes = pack(root).descendants(),
    view;

  var circle = g.selectAll("circle")
    .data(nodes.filter(function(d) {
      return d.height > 0
    }))
    .enter().append("circle")
    .attr("class", function(d) {
      return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root";
    })
    .style("fill", function(d) {
      return d.children ? color(d.depth) : null;
    })
    .on("click", function(d) {
      if (focus !== d) {
        if (d.children) {
          zoom(d), d3.event.stopPropagation();
        } else {
          var nextMonthVal = prompt("Please enter target value you want to set");
          if (nextMonthVal) {
            alert("You have set the target of Rs. " + nextMonthVal + " for next Month");
          }
        }

      }
    });

  var leaf = g.selectAll(".bars")
    .data(nodes.filter(function(d) {
      return d.height == 1
    }))
    .enter()
    .append("g")
    .attr("x", 0)
    .attr("y", 0)
    .attr("height", function(d) {
      return d.x + d.r
    })
    .attr("width", function(d) {
      return d.y + d.r
    })
    .attr("class", "bars")

    .each(function(d) {
      drawBarData(this, this.__data__, d);
    })


  var text = g.selectAll(".label")
    .data(nodes.filter(function(d) {
      return d.height > 0
    }))
    .enter().append("text")
    .attr("class", "label")
    .style("fill-opacity", function(d) {
      return d.parent === root ? 1 : 0;
    })
    .style("display", function(d) {
      return d.parent === root ? "inline" : "none";
    })
    .text(function(d) {
      return d.data.name + " " + d.data.size + " Rs.";
    });

  var node = g.selectAll("circle,.bars,.label");

  svg
    .style("background", color(-1))
    .on("click", function() {
      zoom(root);
    });

  zoomTo([root.x, root.y, root.r * 2 + margin]);

  function zoom(d) {

    var focus0 = focus;
    focus = d;
    var transition = d3.transition()
      .duration(d3.event.altKey ? 7500 : 750)
      .tween("zoom", function(d) {
        var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
        return function(t) {
          zoomTo(i(t), focus);
        };
      });

    transition.selectAll(".label")
      .filter(function(d) {
        return d.parent === focus || this.style.display === "inline";
      })
      .style("fill-opacity", function(d) {
        return d.parent === focus ? 1 : 0;
      })
      .on("start", function(d) {
        if (d.parent === focus) this.style.display = "inline";
      })
      .on("end", function(d) {
        if (d.parent !== focus) this.style.display = "none";
      });
  }

  function zoomTo(v, focus) {
    var k = diameter / v[2];
    view = v;
    node.attr("transform", function(d) {
      return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")";
    });
    circle.attr("r", function(d) {
      return d.r * k;
    });
    if (focus && focus.height == 1) {
      var data2 = focus.children.map(function(d) {
        return d.data
      })
      var data1 = []
      rectwidth = focus.r,
        rectheight = focus.r;
      barsize = data2.length;
      maxDataPoint = d3.max(data2, function(d) {
        return d.size
      });

      var linearScale = d3.scaleLinear()
        .domain([0, maxDataPoint])
        .range([0, rectheight]);


      for (var i = 0; i < data2.length; i++) {
        data1.push({
          name: data2[i].name,
          size: linearScale(data2[i].size)
        })
      }
      bg.attr("transform", function(d) {
        console.log(d);
        return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")";
      })

      bar.attr("x", function(d, i) {
          console.log("D ::: >", d);
          return i * (rectwidth / data1.length);
        })
        .attr("y", function(d) {
          return rectheight - d.size;
        })
        .attr("width", focus.r / data1.length - 2)
        .attr("height", function(d) {
          return d.size;
        });
    }
  }


  function drawBarData(ele, data, d) {
    if (!data && !data.parent)
      return;

    var data2 = data.children.map(function(e) {
      return e.data
    })
    var data1 = []
    rectwidth = d.r,
      rectheight = d.r;
    barsize = data2.length;
    maxDataPoint = d3.max(data2, function(d) {
      return d.size
    });


    var linearScale = d3.scaleLinear()
      .domain([0, maxDataPoint])
      .range([0, rectheight]);


    for (var i = 0; i < data2.length; i++) {
      data1.push({
        name: data2[i].name,
        size: linearScale(data2[i].size)
      })
    }


    bg = d3.select(ele).attr("transform", "translate(" + 0 + "," + 0 + ")").append("g")
      .attr("class", "chart-wrapper")
      .attr("transform", function(d) {
        console.log('BG ::: >>>', d);
        return "translate(" + -d.r / 2 + "," + -d.r / 2 + ")";
      });

    bar = bg.selectAll(".bar")
      .data(data1)
      .enter()
      .append('rect')
      .attr("class", "bar")
      .attr("x", function(d, i) {
        return i * (rectwidth / data1.length);
      })
      .attr("y", function(d) {
        return rectheight - d.size;
      })
      .attr("width", d.r / data1.length - 2)
      .attr("height", function(d) {
        return d.size;
      });
  }
});
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}

.container {
  width: 400px;
}

.node {
  cursor: pointer;
}

.node:hover {
  border: #000;
  border-width: 1.5px;
}

.node--leaf {
  color: white;
}

.label {
  font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
  text-align: center;
  text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
}

.label,
.node--root {
  pointer-events: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="960"></svg>

(json没有足够的空间 - 参考plunkr

按照我的理解,我放置了条形图。但我也希望在每个节点的焦点上放大条形图。我不知道该怎么做。

如果有人有想法或解决方案,请帮助我。

0 个答案:

没有答案