Javascript 为什么重置过滤器在d3 js力有向图中不起作用?

Javascript 为什么重置过滤器在d3 js力有向图中不起作用?,javascript,d3.js,reset,d3-force-directed,Javascript,D3.js,Reset,D3 Force Directed,我试图重新绘制力定向图,并在用户单击“重置过滤器”按钮时将其恢复到原始状态 但它并没有像预期的那样发挥作用。请参考下面的jsfiddle JSIDLE链接: 有人能告诉我这里缺少什么吗?目前,您每次都在重新创建模拟,而且每次都在重新创建可视化:您不是在节点来来往往的情况下进行进入/更新/退出循环,而是将整个过程一笔勾销,从SVG中删除所有内容 现在,我们可以在进行过滤时添加一个进入/更新/退出循环,但是如果我们只需要隐藏已过滤的链接和节点,我们可以只隐藏它们而不是删除它们。我在评论中澄清说,这种

我试图重新绘制力定向图,并在用户单击“重置过滤器”按钮时将其恢复到原始状态

但它并没有像预期的那样发挥作用。请参考下面的jsfiddle

JSIDLE链接:


有人能告诉我这里缺少什么吗?

目前,您每次都在重新创建模拟,而且每次都在重新创建可视化:您不是在节点来来往往的情况下进行进入/更新/退出循环,而是将整个过程一笔勾销,从SVG中删除所有内容

现在,我们可以在进行过滤时添加一个进入/更新/退出循环,但是如果我们只需要隐藏已过滤的链接和节点,我们可以只隐藏它们而不是删除它们。我在评论中澄清说,这种方法是令人满意的,因为它使任务更加容易

对于已过滤掉的节点和链接,我们可以将不透明度设置为
0
并将事件指针指向
none
,对于需要显示的链接和节点,我们可以将这些值重置为
1
all

尽可能多地使用您的代码,我们可以得到如下结果:

// Re-apply the filter each time the input changes:    
d3.select("input").on("keyup", function() {
  // We want to know if we have a value of ""
  var value = this.value.length ? this.value : undefined;

  nodeElements.each(function(d) {
    d.show = false; // by default don't show if a filter is applied.
  })

  // Go through each datum (d.target and d.source) and
  // set a flag to show a node if it is connected (or is) included in the filter
  // also show the link or hide it as needed: 
  linkElements.each(function(d) {
    if(value && d.source.id.indexOf(value) == -1 && d.target.id.indexOf(value) == -1) {
      d3.select(this).attr("opacity",0);
    }
    else {
      d.source.show = d.target.show = true;
      d3.select(this).attr("opacity",1);
    }
  })

  // Now just hide/show text and circles as appropriate.
  nodeElements.attr("opacity",function(d) { return d.show ? 1 : 0 });
  textElements.attr("opacity",function(d) { return d.show ? 1 : 0 });

})
为了简洁起见,我没有在这里设置指针事件,使用类同时设置不透明度和指针事件会更简单。过滤器也是敏感的

由于每对节点和文本的基准是相同的(并在链接基准中引用),我们不需要分别更新每对节点和文本的基准

隐藏节点继续有力作用于它们:它们继续被定位在背景中。如果我们删除了SVG元素,但没有重新定义模拟,那么模拟仍然会计算每个记号的位置。如果我们不想要这两样东西,那么我们需要一种完全不同的方法

下面是一个以代码段形式出现的小示例:

var图={
“节点”:[
{'id':'Menu','group':0},
{'id':'Item1','group':1},
{'id':'Item2','group':1},
{'id':'Item3','group':1},
{'id':'Item4','group':1},
{'id':'Item5','group':1},
{'id':'SubItem1_Item1','group':2},
{'id':'SubItem2_Item1','group':2}],
“链接”:[
{'source':'Menu','target':'Item1','value':1,'type':'A'},
{'source':'Menu','target':'Item2','value':8,'type':'A'},
{'source':'Menu','target':'Item3','value':10,'type':'A'},
{'source':'Menu','target':'Item3','value':1,'type':'A'},
{'source':'Menu','target':'Item4','value':1,'type':'A'},
{'source':'Menu','target':'Item5','value':1,'type':'A'},
/*Item1链接到子项*/
{'source':'Item1','target':'SubItem1_Item1','value':2,'type':'A'},
{'source':'Item1','target':'SubItem2_Item1','value':1,'type':'A'},
/*互联项目*/
{'source':'Item5','target':'Item4','value':2,'type':'A'},
{'source':'Item2','target':'Item3','value':1,'type':'A'},
]};
var宽度=500;
var高度=300;
var color=d3.scaleOrdinal(d3.schemeCategory 10);
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度);
var grads=svg.append(“defs”).selectAll(“radialGradient”)
.数据(图.节点)
.输入()
.附加(“径向梯度”)
.attr(“gradientUnits”、“objectBoundingBox”)
.attr(“cx”,0)
.attr(“fill”,函数(d){返回颜色(d.id);})
.attr(“cy”,0)
.attr(“r”,“100%”)
.attr(“id”,函数(d,i){return“grad”+i;});
grads.append(“停止”)
.attr(“偏移量”、“0%”)
.风格(“停止颜色”、“白色”);
grads.append(“停止”)
.attr(“偏移量”、“100%”)
.style(“停止颜色”,函数(d){返回颜色(d.id);});
var simulation=d3.forceSimulation()
.力(“链接”,d3.力链接().距离(200).id(功能(d){
返回d.id;
}))
.力(“电荷”,d3.力人体().力(-1000))
.力(“中心”,d3.力中心(宽度/2,高度/2));
var g=svg.append(“g”)
.attr(“类”、“一切”);
var linkElements=g.append(“g”)
.attr(“类”、“链接”)
.selectAll(“行”)
.数据(图表.链接)
.enter().append(“行”)
.样式(“笔划宽度”,5.5)
.style(“笔划”、“灰色”)
var nodeElements=g.append(“g”)
.attr(“类”、“节点”)
.selectAll(“圆圈”)
.数据(图.节点)
.enter().append(“圆”)
.attr(“r”,60)
.attr(“笔划”、“fff”)
.attr('stroke-width',21)
.attr(“id”,函数(d){return d.id})
.attr('fill',函数(d,i){return'url(#grad'+i+');})
.on('contextmenu',函数(d){
d3.event.preventDefault();
菜单(d3.mouse(svg.node())[0],d3.mouse(svg.node())[1]);
})
.on('mouseover',selectNode)
.on('mouseout',releaseNode)
.call(d3.drag()
.on(“开始”,拖动开始)
.打开(“拖动”,拖动)
。在(“结束”,dragended));
var textElements=g.append(“g”)//使用g.append而不是svg.append来启用缩放
.attr(“类”、“文本”)
.selectAll(“文本”)
.数据(图.节点)
.enter().append(“文本”)
.attr(“文本锚定”、“结束”)
.text(函数(节点){
返回节点id
})
.attr(“字体大小”,55)
.attr(“字体系列”、“无衬线”)
.attr(“填充”、“黑色”)
.attr(“样式”,“字体大小:粗体;”)
.attr(“dx”,30)
.attr(“dy”,80)
函数勾选(){
链接元素
.attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
节点元素
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;})
.each(d=>{d3.select('#t_'+d.id).attr('x',d.x+10).attr('y',d.y+3);});
文本元素
.attr('x',函数(d){
返回d.x
})
.attr('y',函数(d){
返回d.y
});
}
模拟
.nodes(图.nodes)
。在(勾选)上;
模拟力(“链接”)
.links(图形链接);
函数zoom_actions(){
g、 属性(“转换”,d3.event.transform)
}
函数dragstarted(d){
如果(!d3.event.active)simulation.alphaTarget(0.3).resta
// Re-apply the filter each time the input changes:    
d3.select("input").on("keyup", function() {
  // We want to know if we have a value of ""
  var value = this.value.length ? this.value : undefined;

  nodeElements.each(function(d) {
    d.show = false; // by default don't show if a filter is applied.
  })

  // Go through each datum (d.target and d.source) and
  // set a flag to show a node if it is connected (or is) included in the filter
  // also show the link or hide it as needed: 
  linkElements.each(function(d) {
    if(value && d.source.id.indexOf(value) == -1 && d.target.id.indexOf(value) == -1) {
      d3.select(this).attr("opacity",0);
    }
    else {
      d.source.show = d.target.show = true;
      d3.select(this).attr("opacity",1);
    }
  })

  // Now just hide/show text and circles as appropriate.
  nodeElements.attr("opacity",function(d) { return d.show ? 1 : 0 });
  textElements.attr("opacity",function(d) { return d.show ? 1 : 0 });

})