javascript - 如何在Vega JS中实现树节点切换?

标签 javascript charts tree vega

我正在使用Vega JS用于构建树形图。总的来说,我的问题如下:

Vega 文档有一个很棒的 example of tree layout 。我怎样才能扩展它并具有折叠和展开其节点的能力?

更具体地说,让我们考虑一下我正在构建的树形图的示例 here in Vega Editor .

如果您单击节点,它们将切换(展开或折叠),使您可以看到树的特定分支。除非您尝试折叠顶级节点(区域),同时保持二级节点(区域)展开,否则此功能可以正常工作。在这种情况下,树将如下所示:

broken tree screenshot

发生这种情况是因为我处理此交互的方式:

  1. 当您点击节点时,会触发 toggledNode 信号,进而触发 expandedNodes 数据数组中的 toggle 操作。 IE。通过单击一个节点,我可以将该节点添加到 expandedNodes 数组中或从中删除(更准确地说,我们添加/删除仅具有 name 属性的简化对象)
  2. 因此,expandedNodes 数据包含有关哪些节点显式扩展的信息。但它不知道这些展开的节点是否位于折叠的父节点内部。
  3. 然后,为了找出哪些节点实际上可见,我使用 visibleNodes 数据。在那里,我使用以下表达式应用 filter 转换: !datum.parent || indata('expandedNodes', 'name', datum.parent)。 IE。我仅检查上一级:如果节点的父节点存在于 expandedNodes 数组中,我认为该节点可见。

问题如下:我找不到任何方法可以跨多个级别扩展此功能。

也许我可以编写一些钩子(Hook)来检查 2 或 3 个级别的相同条件,例如:

!datum.parent ||
  indata('expandedNodes', 'name', datum.parent) && 
  indata('expandedNodes', 'name', datum.myCustomFieldWithParentNode.parent) && 
  indata('expandedNodes', 'name', datum.myCustomFieldWithParentNode.myCustomFieldWithParentNode.parent)

但是对于这样一个简单的问题来说似乎太复杂了,而且这也不是最终的解决方案。理论上,一棵树可能包含几十个嵌套级别:那该怎么办?

我在 Vega 中发现了一个有用的表达式:treeAncestors 。我可以轻松地用 JavaScript 编写一个解决方案,其中有循环和数组方法,例如 .some().every()。但显然 Vega 不支持任何表达式来迭代数组。因此,即使我可以使用 treeAncestors 函数获取树节点祖先数组,但我无法用它做任何事情来验证所有祖先是否都已展开。

要么我的方法是错误的,有人可以找到更好的算法来执行相同的操作,该算法不需要迭代数组(dataindata 表达式除外) - 或者这是 Vega 当前的限制。

最佳答案

您可以使用treeAncestors,然后使用展平变换来获取可以查询的数据集。在你的情况下,它看起来像:

{
  "transform": [
    {
      "as": "treeAncestors",
      "type": "formula",
      "expr": "treeAncestors('tree', datum.id, 'root')"
    }
  ],
  "name": "tree-ancestors",
  "source": "tree"
},
{
  "transform": [{"fields": ["treeAncestors"], "type": "flatten"}],
  "name": "tree-ancestors-flatt",
  "source": "tree-ancestors"
},
{
  "transform": [
    {
      "type": "filter",
      "expr": "indata('selected', 'value', datum.treeAncestors.id)"
    }
  ],
  "name": "filtered",
  "source": "tree-ancestors-flatt"
},
{
  "transform": [{"type": "aggregate", "groupby": ["id"]}],
  "name": "filtered-aggregate",
  "source": "filtered"
},
{
  "transform": [
    {
      "type": "filter",
      "expr": "indata('filtered-aggregate', 'id', datum.id) "
    }
  ],
  "name": "filtered-tree",
  "source": "tree"
}

关于javascript - 如何在Vega JS中实现树节点切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69302893/

相关文章:

javascript - 如何在 Firefox 中使用 XUL 创建底部停靠面板?

javascript - 尝试调用从 AJAX 调用传回的 JS 代码

javascript - 如何用图像而不是颜色填充 D3 SVG?

excel - 数据图表在 Excel 中显示一天中的时间

javascript - jquery 图表应该显示没有数据的刻度标签

javascript - 当 Firefox 中一切正常时,跟踪 IE 中的显示错误

java - 如何使图表显示数组元素

database - 检索按 PostgreSQL 的 Ltree 模块下的列排序的完整层次结构

c++ - 在声明行处查看未声明的错误

d3.js - d3js 中从一个强制有向图到另一个图的转换