在D3中绘制具有不同半径的饼图(将力网与饼图结合)

时间:2015-03-12 04:21:15

标签: javascript d3.js charts

我想在D3中将饼图与强制网络结合起来。我目前正在使用部队网络(如下所示)。我想将每个气泡变成饼图。这是可能的,因为它们具有不同的半径。任何一般方法将不胜感激。谢谢!

这是当前的javascript代码:

d3.json("data/d3data.json", function(error, graph) {
  var new_nodes = convert(graph.nodes);

  force
      .nodes(new_nodes)
      // .links(graph.links)
      .start();

  var root = new_nodes[0];
  root.fixed = true;

  var loading = svg.append("text")
    .attr("x", width / 2)
    .attr("y", height / 2)
    .attr("dy", ".35em")
    .style("text-anchor", "middle")
    .text("Simulating. One moment please…");

  var node = svg.selectAll("svg")
      .data(new_nodes)
    .enter().append("svg")
    .attr("width", function(d) { return Math.sqrt(d.followersCount/100)*2;})
    .attr("height", function(d) { return Math.sqrt(d.followersCount/100)*2;});

  var g = node.append("g")
      .attr("transform", function(d) { return "translate(" + d.r + "," + d.r + ")"});

  var g_2 = node.selectAll("g")
          .data(function(d) {
            console.log(pie(d.FFratio));
            return pie(d.FFratio);})
          .enter() .append("g");

  g_2.append("path")
        .attr("d", d3.svg.arc().outerRadius(10))
        .style("fill", function (d, i) {
        return color(i);
    })

  function tick(){
    var node_x = 0;
    var node_y = 0;
    node.attr("x", function(d) { node_x = d.x; return d.x; })
        .attr("y", function(d) { node_y = d.y;return d.y; });
  }

loading.remove();

 force.on("tick", function ticky(e){
  var q = d3.geom.quadtree(graph.nodes),
      i = 0,
      n = graph.nodes.length;
  while (++i < n) q.visit(collide(graph.nodes[i]));

  tick();

 });

 function convert(node_list){
  var result = [];
  var current_node = {};

  count = 0;

  while (++count<node_list.length){

      current_node = node_list[count];
      current_node.r = Math.sqrt(current_node.followersCount/100);
      var followingR = current_node.followingCount/(current_node.followersCount+current_node.followingCount)*100;
      var followerR = 1 - followingR;
      current_node.FFratio = [followingR, followerR];
      result.push(current_node);
  };
  return result;
 };

 function collide(node) {
  var node_r = Math.sqrt(node.followersCount/100),
      r = node_r + 100,
      nx1 = node.x - r,
      nx2 = node.x + r,
      ny1 = node.y - r,
      ny2 = node.y + r;
  return function(quad, x1, y1, x2, y2) {
    if (quad.point && (quad.point !== node)) {
      var x = node.x - quad.point.x,
          y = node.y - quad.point.y,
          l = Math.sqrt(x * x + y * y),
          r = node_r + Math.sqrt(quad.point.followersCount/100);
      if (l < r) {
        l = (l - r) / l * .5;
        node.x -= x *= l;
        node.y -= y *= l;
        quad.point.x += x;
        quad.point.y += y;
      }
    }
    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
  };


    };
});

enter image description here

1 个答案:

答案 0 :(得分:5)

此处an example我刚刚根据clustered force layout进行了编码。

关键是用circle替换聚类g的力,然后你可以在其中循环并构建饼图:

var pies = svg.selectAll(".pie")
  .data(nodes)
  .enter().append("g")
  .attr("class","pie")
  .call(force.drag);

pies.each(function(d,i){

  var pieG = d3.select(this);

  var arc = d3.svg.arc()
    .outerRadius(d.radius)
    .innerRadius(0);

  var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { 
      return d;
    });

  var data = [Math.random(), Math.random(), Math.random(), Math.random()];

  var g = pieG.selectAll(".arc")
    .data(pie(data))
    .enter().append("g")
    .attr("class", "arc");

  g.append("path")
    .attr("d", arc)
    .attr("fill", function(d,i){
      return colors(i);
    })
});

产生这个:

enter image description here