简体   繁体   English

D3气泡图/包装布局 - 如何使气泡从最大气泡辐射到最小气泡?

[英]D3 bubble chart / pack layout - How to make bubbles radiate out from the largest bubbles to the smallest?


So I am using the same code as this D3 gallery example (with my own data): 所以我使用与这个D3库示例相同的代码(使用我自己的数据):

http://bl.ocks.org/mbostock/4063269 http://bl.ocks.org/mbostock/4063269


I'd like to get a bubble chart where the circles are arranged with the biggest in the center and then radiating out to the smallest. 我想得到一个气泡图,其中圆圈的中心位置最大,然后辐射到最小的圆圈。


Here is a mock up I created in Photoshop: 这是我在Photoshop中创建的模拟:

我真正想要的是什么



Here is what I get when I use the example (the default circle packing algorithm with default sort): 以下是我使用该示例时获得的内容(默认排序算法的默认圆形打包算法):

默认包装



I tried tweaking the sort (including trying d3.ascending and d3.descending). 我尝试调整排序(包括尝试d3.ascending和d3.descending)。 The best I could come up with just basically subverts the sort with a constant (ha!) but still is far from what I'd like: 我能想出的最好的东西基本上是用一个常数来破坏排序(哈哈!),但仍然远非我想要的:

//...
.sort( function(a, b) { return -1;} )
//...

我可以通过调整排序来获得最佳效果



Ok, so any chance this can be done without having to alter the actual D3 pack layout algorithm? 好的,那么在不必改变实际的D3包布局算法的情况下可以做到这一点吗? If not, perhaps someone has extended or modified the pack layout and could tell me the 5 lines I could change in the D3 source to hack this. 如果没有,也许有人已经扩展或修改了包布局,并且可以告诉我可以在D3源中更改的5行来破解它。



Thanks in advance! 提前致谢!


Edit: 编辑:

As requested, here is the code I am using. 根据要求,这是我正在使用的代码。 Basically the same as the linked sample above, with a few superficial changes as indicated by the commented lines: 基本上与上面的链接样本相同,有一些表面的变化,如注释行所示:

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

var bubble = d3.layout.pack()
//  .sort(null)
//  .sort(d3.ascending)
//  .sort(d3.descending)
    .sort( function(a, b) { return  -1;} ) // basically a < b always
    .size([diameter, diameter])
    .padding(1.5);

var svg = d3.select("body").append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
    .attr("class", "bubble");

d3.json("data.json", function(error, root) 
{
  var node = svg.selectAll(".node")
        .data(bubble.nodes(classes(root))
        .filter(function(d) { return !d.children; }))
        .enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

  node.append("title")
      .text(function(d) { return d.className + ": " + format(d.value); });

  node.append("circle")
      .attr("r", function(d) { return d.r; })
      .style("fill", function(d) 
            { 
                // return color(d.packageName); 
                return color(d.value); // this gives a different color for every leaf node
            });

  node.append("text")
      .attr("dy", ".3em")
      .style("text-anchor", "middle")
     // .text(function(d) { return d.className.substring(0, d.r / 3); });
});

// Returns a flattened hierarchy containing all leaf nodes under the root.
function classes(root) 
{
  var classes = [];

  function recurse(name, node) {
    if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
    else classes.push({packageName: name, className: node.name, value: node.size});
  }

  recurse(null, root);
  return {children: classes};
}

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

And my data.json file: 和我的data.json文件:

{
    "name": "Root",
    "children": [
        {
            "name": "Leaf",
            "children": null,
            "size": 2098629
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 104720
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 5430
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 102096
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 986974
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 59735
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 1902
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 120
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 870751
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 36672
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 274338
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 517693
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 145807
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 476178
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 11771
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 153
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 2138
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 8436
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 3572
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 120235
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 210945
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 56033
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 358704
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 295736
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 26087
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 33110
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 3828
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 1105544
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 98740
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 80723
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 5766
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 1453
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 10443176
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 14055
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 1890127
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 404575
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 272777
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 1269763
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 5081
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 3168510
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 717031
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 88418
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 762084
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 255055
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 535
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 81238
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 17075
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 5331
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 74834
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 110359
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 27333
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 143
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 12721
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 529
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 115684
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 3990850
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 6045060
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 2445766
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 479865
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 105743
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 183750
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 661
        },
        {
            "name": "Leaf",
            "children": null,
            "size": 11181
        }
    ],
    "size": 41103329
}

All you need to do is to specify: 您需要做的就是指定:

.sort(function(a, b) {
    return -(a.value - b.value);
})

This is different than specifying .sort(d3.ascending) or .sort(d3.descending) , since d3.ascending and d3.descending are defined as 这与指定.sort(d3.ascending).sort(d3.descending) ,因为d3.ascendingd3.descending定义为

function(a, b) {
  return a < b ? -1 : a > b ? 1 : 0;
}

and

function(a, b) {
  return b < a ? -1 : b > a ? 1 : 0;
}

respecitevly, and the pack layout is affected by their "insensitivity" to the difference of data points. 相应地,包装布局受到它们对数据点差异的“不敏感性”的影响。

This is my test example: (with your data) jsfiddle 这是我的测试示例:(使用您的数据) jsfiddle

在此输入图像描述


Experimentally, I applied also following sort function: (it is a kind of hybrid) 在实验上,我也应用了以下排序功能:(它是一种混合)

.sort( function(a, b) {
    var threshold = 10000000;
    if ((a.value > threshold) && (b.value > threshold)) {
        return -(a.value - b.value);
    } else {
        return -1;
    }
})

... and for values for threshold of 10000000, 3000000, 1000000, 300000, 100000, 30000 respectively I got: jsfiddle ...并且对于阈值分别为10000000,3000000,1000000,300000,100000,30000的值我得到: jsfiddle

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM