我正在研究d3可视化以创建一个sunburst。我还添加了一个搜索特定弧的功能,以便sunburst显示仅包含搜索标签的弧。如果初始对象是:
{
"name": "root",
"children": [
{
"name": "A",
"color": "red",
"children": [
{
"name": "B",
"color": "red"
}
]
},
{
"name": "C",
"color": "red",
"children": [
{
"name": "D",
"color": "red"
}
]
},
{
"name": "E",
"color": "red",
"children": [
{
"name": "B",
"color": "red"
}
]
}
]
}
我想对此进行过滤,使其返回整个层次结构,其中包含层次结构中任何位置的搜索名称。以下是搜索"名称"所需的示例输出:" B"
{
"name": "root",
"children": [
{
"name": "A",
"color": "red",
"children": [
{
"name": "B",
"color": "red"
}
]
},
{
"name": "E",
"color": "red",
"children": [
{
"name": "B",
"color": "red"
}
]
}
]
}
请告诉我是否还需要其他任何东西。谢谢。
我尝试过滤的代码段。
var path = svg.selectAll("path")
.data(partition.nodes(root))
.enter()
.append("path")
.filter(function(d){
return (d.name=="B");
})
.attr("d", arc)
.style("fill", function(d) {
console.log(d.name);
return color((d.children ? d : d.parent).name);
})
这仅返回" name":" B"弧而不是层次结构。
答案 0 :(得分:0)
如果你想让.filter()方式为你工作,你必须展平你的JSON数据应用一个过滤器,然后取消它。如果您有兴趣,可以查看展平和不展平。 我个人更喜欢深度优先搜索(或bfs也工作)和修剪所需的方法。让我们假设您的json数据存在于mydata javascript var:
中d3.json("jsonData.json",function(error,jsonData){
if(error)
return console.warn(error);
var mydata = jsonData;
dfs(mydata,'B');
});
现在你的dfs()函数看起来像这样:
function dfs(data,label){
if(!('children' in data))
return data.name==label;
for(var i=0;i<data.children.length;++i)
if(dfs(data.children[i],label)==flase)
data.children.splice(i--,1);
return data.children.length > 0 || data.name==label;
}
这里发生的是我们正在深度优先搜索JSON数据。第一个IF条件检查我们是否处于叶节点级别,如果名称&#39;则返回false。财产不是什么,而是&#39; B&#39;接下来,我们遍历当前节点的所有子节点,为每个子节点调用dfs(),如果返回false则修剪该子节点。最后,如果当前节点的所有子节点都已被修剪,并且如果名称为&#39;那么我们将返回false。当前节点的属性不是&#39; B&#39; (必须从层次结构中修剪非叶节点的条件)。希望这可以帮助。如果我错过了什么,请告诉我。
答案 1 :(得分:0)
我的预感是你要在sunburst中为搜索节点及其父节点着色。
为了做到这一点,我创建了一个函数,以递归方式为节点的父颜色着色:
function colorGraph(node){
var sel = svg.selectAll("path").filter(function (d) {
return (node==d);
});
sel.style("opacity", 1);
//if parent present change its opacity
if(node.parent){
colorGraph(node.parent)
}
}
完整的工作代码here
答案 2 :(得分:0)
您需要预过滤,而不是在D3管道中进行过滤。
定义一个过滤函数,我们将调用hasName
来检查特定对象是否具有所需的名称,或者递归地,如果它的任何子对象具有它:
// Does the object contain a specified name, however many levels down?
function hasName(obj, name) {
return function _hasName(o) {
return o.name === name || (o.children || []).some(_hasName);
}(obj);
}
现在过滤:
data.children = data.children.filter(function(child) { return hasName(child, 'B'); });