有条件地递归地改变所有节点和边缘的不透明度(d3)

Dan*_*Dan 8 javascript recursion dictionary filtering d3.js

更新:我在这里创建了一个JSFiddle.请发布一个更新的小提琴你的答案.

我有动态过滤器,用户可以应用于数据,但是它们会改变节点的不透明度以指示过滤进出的内容(过滤后的"out"元素仍然是部分可见的,并且实际的d3 filter()函数未被使用(有意)) .我还在每个被过滤掉的节点上设置了一个属性(例如node = {"name": "test", "isFilteredOut": true};).因此,对于这个问题的目的,即使我使用"过滤器"这个词,它实际上只是一个条件样式更改(我将尝试在此帖中将"过滤器"一词放在引号中作为提醒) .

这一切都很好,但现在我想递归"过滤"所有子节点和"过滤"节点的边缘,以及连接初始"过滤"节点到其未过滤掉的父节点的边缘.

我能找到的所有示例都以点击事件开始,因此可以this用来获取所选初始节点的数据.我没有这种奢侈,因为使用不在图表本身内的UI元素来应用过滤器.

我目前"过滤"节点,如下所示:

node.style("opacity", function(n) {
    if (my_filter_conditions) {
        return 1;
    } else {
        n.isFilteredOut = true;
        return 0.1;
    }
});
Run Code Online (Sandbox Code Playgroud)

我基本上需要做的是:

  1. 递归地选择当前"已滤除"节点的所有子节点,并且也"过滤"那些节点(即将它们的不透明度改变为0.1并设置n.isFilteredOut = true;).

  2. 将所有边的不透明度更改为0.1,其中源节点目标节点被"过滤掉"(即n.isFilteredOut = true;在边缘的任一端)

我尝试了什么

我不知道如何访问源节点和目标节点的数据,只给出每个边缘的索引(记住我没有this从点击事件开始的节点).我尝试传递从边缘获得的节点索引来获取节点数据:

var node_data = d3.select(current_edge.source.index).datum();
Run Code Online (Sandbox Code Playgroud)

但是,这导致d3库中的错误与this.node()null 相关(因此在此处传递索引不起作用).

我也尝试通过嵌套函数来处理边缘,处理传递给node.style()函数的函数内部的链接,然后它尝试处理每个节点上的所有边缘,我无法得到它来提供所需的结果.

link.style("opacity", function (e) {
    return ( (n.isFilteredOut)
            && (n.index==e.source.index | n.index==e.target.index) ) ? 0.1 : 1;
});
Run Code Online (Sandbox Code Playgroud)

这是我试图"过滤掉""滤出"节点两侧的边缘,但是当我出于某种原因使用它时,没有任何边缘被过滤掉(似乎根本没有发生任何事情).

更新:我在这里创建了一个JSFiddle.

关于小提琴的注释:

  • 我知道这很简单(它应该是一个最小的工作示例)
  • 实际应用程序包含适用于类型的过滤器(即使只是搜索特定设备/部件/等),因此逻辑能够有条件地遵循"链"仅对那些节点具有重要性 node.isFilteredOut = true;
  • 在此示例中,正确答案将导致创建过滤设备也将过滤掉所有部件的情况
  • 使用dataSet自身进行任何过滤的解决方案将无法正常工作,因为我的大部分数据都是从各种JSON源动态填充的.随时与工作nodes,edges,links,node,和/或link.
  • 请不要重写我的过滤方法.是的,我知道eval()陈述并不好.但这不是关于如何最好地应用无限联合滤波器的问题,而是基于应用的滤波器递归地改变节点和边缘的不透明度

man*_*iot 2

这是一种可能的方法,它实现了递归过滤(如果设备被过滤,则其部分被过滤)和基于节点过滤的链接过滤:http ://jsfiddle.net/Lsr9c8nL/4/

我改变了你实现过滤器的方式。使用字符串来构建过滤器,然后eval()被认为是非常糟糕的,因为工具不能用 做太多事情eval(),例如检测错误或优化浏览器上的 JS 代码。

我直接在 上进行过滤dataSet,而不是在节点上(您必须查询节点type并比较字符串,这很慢)。直接在数据集上执行此操作还可以轻松查找给定部件的设备是什么。

诀窍基本上是每次都重新绘制整个图表,并仔细使用 d3 的exit,enterupdate选择。如果需要,这还允许您添加动画