使用 nest() 和 rollup 的圆包布局

Circle pack layout using nest() and rollup

我正在尝试使用 nest().rollup 创建一个圆包图。我收到以下错误:

Error: Invalid value for <g> attribute transform="translate(undefined,undefined)"
Error: Invalid value for <circle> attribute r="NaN"

我希望根据每个国家/地区的公司数量来调整圆圈的大小。我正在尝试改编 Mike Bostock 的 Flare circle-pack 示例。

如果有人能指出任何信息的方向,我将不胜感激。

JS代码:

var diameter = 960,
    format = d3.format(",d");

var pack = d3.layout.pack()
    .size([diameter - 4, diameter - 4])
    .value(function(d) { return d.size; });

var svg = d3.select("body").append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
  .append("g")
    .attr("transform", "translate(2,2)");

//Get data
d3.json("data/countriesNested.php", function(error, data){

  var submissionsByCountry = d3.nest()
      .key(function(d) { return d.Country; })
      .key(function(d) { return d.Organisation; })
      .rollup(function(leaves) { return leaves.length; })
      .entries(data);    

  var node = svg.datum(data).selectAll(".node")
      .data(pack.nodes)
    .enter().append("g")
      .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
      .attr("transform", function(d) { return "translate(" + d.cx + "," + d.cy + ")"; });

  node.append("title")
      .text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });

      node.append("circle")
          .attr("r", function(d) { return d.r; });

});

d3.select(self.frameElement).style("height", diameter + "px");

</script>

数据文件(来自 MySQL 使用 PHP 脚本):

    [
  {
    "Country":"USA",
    "ID":4,
    "Organisation":"Company 1"
  },
  {
    "Country":"USA",
    "ID":5,
    "Organisation":"Company 2"
  },
  {
    "Country":"USA",
    "ID":6,
    "Organisation":"Company 3"
  },
 {
    "Country":"FRANCE",
    "ID":19,
    "Organisation":"Company 4"
  },
  {
    "Country":"FRANCE",
    "ID":24,
    "Organisation":"Company 5"
  },
  {
    "Country":"GERMANY",
    "ID":10,
    "Organisation":"Company 6"
  },
  {
    "Country":"ITALY",
    "ID":7,
    "Organisation":"Company 7"
  },
  .....

感谢阅读。

那么,您想要一个父圆(我们称它为世界),子圆代表每个国家/地区的大小与 JSON 数组中的条目数有关?

d3.json("data/countriesNested.php", function(error, data) {

    var submissionsByCountry = d3.nest()
      .key(function(d) {
        return d.Country;
      })
      .rollup(function(leaves) {
        return leaves.length;
      })
      .entries(data);

    var root = {
      "key": "world",
      "children": submissionsByCountry
    };

    ...

这会给你一些非常类似于 flare.json 的东西。

接下来,您需要为 d3 指定适合您圆圈大小的 accessor

var pack = d3.layout.pack()
  .size([diameter - 4, diameter - 4])
  .value(function(d) {
    return d.values; //<-- this comes from your roll-up and is the count.
  });

最后,您似乎更改了示例代码以访问结果节点数据中不存在的 cxcy 属性:

var node = svg.datum(root).selectAll(".node")
  .data(pack.nodes)
  .enter().append("g")
  .attr("class", function(d) {
    return d.children ? "node" : "leaf node";
  })
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")"; //<-- this is .x, .y
  });

这是一个 example

您的代码中存在一些需要修复的错误:

  1. 您需要为您的包布局中的子项和值设置访问器函数:

    var pack = d3.layout.pack()
      .size([diameter - 4, diameter - 4])
      .children(function(d) {
        return d.values;  // accessor for children
      })
      .value(function(d) {
        return d.values;  // accessor for values
      });
    
  2. 您的 d3.nest() returns 一个数组,但 d3.pack() 要求您提供包含层次结构的根 对象 。您必须创建一个根对象并将嵌套数组放入其中:

    var countryRoot = {
        key: "root",
        values: submissionsByCountry
    };
    
  3. 在您的代码中,您将数据嵌套到 submissionsByCountry 但您没有在其他任何地方使用此变量。因此,在将数据绑定到 svg 时,您显然必须参考它。这是通过上面提到的根对象完成的,该对象后来绑定到 svg.

    var node = svg.datum(countryRoot).selectAll(".node")
    
  4. 包布局添加到您的数据节点的属性包括值 xy,而您将它们称为 cxcy<svg:circle> 的属性,但不存在于您的数据中。因此,您收到了 transform="translate(undefined,undefined)" 错误消息。您应该这样使用这些属性:

    .attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });
    

我整理了一个工作 plunk