在 d3 的打包布局中是否有一种方法可以手动设置子节点的半径,其大小相对于父半径,然后让其他子节点根据剩余空间并使用现有的“按 child 数量计算大小”?
我想做的是: 1. 为每个节点添加一个与父节点同名的节点到子数组 2. 将这个额外子项的半径设置为具有足够大的半径以包含文本并确保与其邻居不重叠 3. 在这个额外节点上将填充和描边设置为无 4. 在此额外节点上通过 css 将点击交互设置为无 5. 只使用这些额外的节点来显示“他们的”名字(也就是他们 parent 的名字)
结果将是一个填充圆,其标签有专门指定的空间。如果没有手动设置额外子节点的半径,这是行不通的,因为它的大小是根据子节点的数量自动确定的。 (添加未填充/未描边的子节点来补偿是非常低效的。我不认为第一次黑客攻击的第二次黑客攻击是不值得的)
最佳答案
请检查这是否对您有帮助。带有“extra”类的红色背景圆圈是带有 parent 姓名的额外圆圈。
var root = {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality", "size": 3534},
{"name": "LinkDistance", "size": 5731},
{"name": "MaxFlowMinCut", "size": 7840},
{"name": "ShortestPaths", "size": 5914},
{"name": "SpanningTree", "size": 3416}
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker", "size": 7074}
]
}
]
},
{
"name": "animate",
"children": [
{"name": "Easing", "size": 17010},
{"name": "FunctionSequence", "size": 5842},
{
"name": "interpolate",
"children": [
{"name": "ArrayInterpolator", "size": 1983},
{"name": "ColorInterpolator", "size": 2047},
{"name": "DateInterpolator", "size": 1375},
{"name": "Interpolator", "size": 8746},
{"name": "MatrixInterpolator", "size": 2202},
{"name": "NumberInterpolator", "size": 1382},
{"name": "ObjectInterpolator", "size": 1629},
{"name": "PointInterpolator", "size": 1675},
{"name": "RectangleInterpolator", "size": 2042}
]
},
{"name": "ISchedulable", "size": 1041},
{"name": "Parallel", "size": 5176},
{"name": "Pause", "size": 449},
{"name": "Scheduler", "size": 5593},
{"name": "Sequence", "size": 5534},
{"name": "Transition", "size": 9201},
{"name": "Transitioner", "size": 19975},
{"name": "TransitionEvent", "size": 1116},
{"name": "Tween", "size": 6006}
]
},
]
};
var addExtraNode = function(item, percentSize){
var percentSizeOfNode = percentSize || 60; //if not given it will occupy 60 percent of the space
if(!item.children){
return;
}
var totalChildSize = 0;
item.children.forEach(function(citm, index){
totalChildSize = totalChildSize + citm.size;
})
var nodeSize = (percentSizeOfNode / 50) * totalChildSize;
var name = 'NAME: '+item.name;
item.children.push({
'name': name,
'size': nodeSize,
'isextra':true
})
item.children.forEach(function(citm, index){
if(citm.children){
addExtraNode(citm, percentSize);
}
})
};
addExtraNode(root, 55);
var diameter = 500,
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)");
var node = svg.datum(root).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) {
if(d.isextra){
return 'extra';
}
return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle")
.attr("r", function(d) { return d.r; });
node.filter(function(d) { return !d.children; }).append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.name.substring(0, d.r / 3); });
circle {
fill: rgb(31, 119, 180);
fill-opacity: .25;
stroke: rgb(31, 119, 180);
stroke-width: 1px;
}
.leaf circle {
fill: #ff7f0e;
fill-opacity: 1;
}
text {
font: 10px sans-serif;
}
.extra circle{
fill:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
关于javascript - D3 圆形包装透明标签解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31623869/