javascript D3气泡图/包装布局 - 如何使气泡从最大的气泡辐射到最小的气泡?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24336898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
D3 bubble chart / pack layout - How to make bubbles radiate out from the largest bubbles to the smallest?
提问by SoldierOfFortran
So I am using the same code as this D3 gallery example (with my own data):
所以我使用与这个 D3 画廊示例相同的代码(使用我自己的数据):
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). 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:
我尝试调整排序(包括尝试 d3.ascending 和 d3.descending)。我能想出的最好的只是基本上用一个常数(哈!)颠覆了排序,但仍然远不是我想要的:
//...
.sort( function(a, b) { return -1;} )
//...
Ok, so any chance this can be done without having to alter the actual D3 pack layout algorithm? 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 包布局算法的情况下做到这一点?如果没有,也许有人扩展或修改了包布局,并可以告诉我我可以在 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
}
回答by VividD
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)
or不同.sort(d3.descending)
,因为d3.ascending
和d3.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