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

2024-02-22

我在用着Vega JS https://vega.github.io/vega用于构建树形图。总的来说,我的问题如下:

Vega 文档有很棒的树形布局示例 https://vega.github.io/vega/examples/tree-layout/。如何通过折叠和展开其节点的能力来扩展它?

更具体地说,让我们考虑一个我正在构建的树形图的示例在 Vega 编辑器中 https://vega.github.io/editor/?#/url/vega/N4IgJAzgxgFgpgWwIYgFwhgF0wBwqgegIDc4BzJAOjIEtMYBXAI0poHsDp5kTykSArJQBMARkoArCGwB2IADQgcSACYqaMsmgGKkDTGwg0AXnDShMATxxn0ylQpAAnOEdNpMThnAC%20io2QySAA2EGgA2qBBCLYYbE4mspghjsQh3mgAZiEQcIpMGg6ooBo4%20mggsHBQANZMbAAeID5%20UUgxFfE0cDLJmOxyigw4KkiYsTBdxkkhAAQA-LMA5JMJ070hS7Ooy6RO-VCbzfJtHegybCpwAOo0KvSp6bbCAAwvrSDRsRdXABJwNDIWEewQyqFEoneJ0%207W%20lzgACE2AwZCowkMRmMJlMZsEFrNwj84P9AVhZgBqWYAFhe8lmRNu9xgFNmAA4XgBdbYEhl3egs150okkoGYFnsjnHU6xTxwOAAFScSBkEEy8QQAAUnGw8I5hqNxhVwqtEhs8YslpYtjslg0lnSTetkublnbuZb7csrjh6J6lrAaMEVC4ZEtJR8vhUDGQyME4CoAHLwkFgmQMYLBRSyCKgOCkXphdAIZG5YZ6zGG87p4LNDk%20DmKA0oVCRGFnECysyKNKg1w5tuxJP7eBICCYRzKEPj1BpjONmgxFUDCoAJXIy8bY2brcj6HlK4aswAamxQR1u080KIAMxvO8R2EVBMH4%20nhjnkA9sEAdlZ7Le9YPu2ACydyzAAgpgwTKgcE5IFOT7xPQcCjuO86LkY2boAAIjQY4JFAaEgE2-a7iA%206HieZ5dp%20l6oP%2097QmRz6UW%20H5frYNJ3u8dZMY%206AJnAADuswAKKaNBqJwQhAlISOY6OOoGHLjheGeDQhGKVupH8eRL5Ue%20NEcdo3FQtKT76WxRl0def73rx5noAiIT9MWLizMB2HST004gKBKgQVBMEaYpC49Jhch7nATgJAYTiWFpyQ6e2FGvtRKacaZQGDpZ6UXr2aCvNxgF8e2CIMJk2TBGwswJgAmt5vQVP5gWSbB6HhSp5HRbF8QJZuSUto5emsXltEFagXGMcNLFpYZGWFVlDkDhUSJjrIHngY1vmCSJ4mxsqDgdUuWHdTFdB9Yl27DalBnsXRkLFaVOWjfN%20VgqIdkActZG-PBmBqk4AUAMLyttT7CWJEmHaFymnfKPUXfFV3JbEt1WQtk1Zc9FmvfdE1FfZ9aKJ4yqquq-ZWDYFT4WMNCZP1IA1HACXnI%20iiTj5ADSLMVJzTUfFTMouDRMT0JcUZ3Izbi2KAARBDW6DhEJfIwA6AKiuGihEgAyiYssgPLKTnPCSIomixyG3Ak501hVW5LohZy4CCtRiLipk4DmrarqLQ-bpcANMoqLxkmVzouN3iFjuulDshqG1lmkWtupMbRVGbAxnGibJiTmexjK%20fZ2HZglcNxB4TQTBxiXEfSAwThQMLcqOKTKpe5T1ixJkgbjE4jiBzg-foAAhAa76UPzYoAD7T7MhRbgAFEsg%20HaH8IQH6XyeuPCCT-BPkAJS1tlFQV0Y1dwAAMhoNR18ijfNzRbfk04CCd9T6CdsEt9hILXcVB7sEPuA8g7DxAAvZIy9V4hxzuHLesId5jAnvXR%20lAvjH0Ag2EAyAnB3w-rEZQDxFCZG1O-YoxFtLoHPlXOMN8ZD4L8BA3o0UkCERoKQLIOQ8gdiVO3CmQ0OwAPQD-BhRCYCOC6D5cwhsXbGxAFIjY-RsxMIgDAJAn9iI0CQGQWQKR-APybgADRkYPcBu9KAWNQU3Sgh5KSL0dLifEvImQEGENyF4mCDENybg1ChZiKgWKsYYuAlBLAsgcTiM0%20IXjcmFBrLAbivEdngmQOAmATH%20LAYE5Be8LHJCcGkzAtjZgAFpZiRLWE4xYLj6BuI8ckgpRS-G5myegIJuTKBNPSWEspFTHHRMWLEnY8TSSYCSc0YmIAehQGTBQ-UWIZH4TYMzGRxl0AAGIoDbMtuImRPc4BBj5mMCRLQWjQiFhUMg2oyza10p2EujhSFsHIaAbITdpzDTFgRCOJFqGV0vrXJ53QjntO0uc2RgQciowzlndeVwJwMDUZ0fQ6ck79jzD5QslQf61HLAaWIFiAxBhDLMAAfLMWJixgBfB2BYr4Pg4nVhPtg6AIQ%20yCLIt8jSEAdaHDjK3YRIAmAw0bC8pAGgZF-Jwekn5wLDlFEjqXRQfC0lLPGDgNA14ABsTD7DqE0GgF4lBRAquRFJVAnhvBTJmXM3MLDh6gBVkyJZcjFafHhIyB4TD4BjNdVC91ozRSWwaFAfZILFVNCYZYMNFCDmgpAAlJhsynAyGiiuVQNAkVrJssmhu0hHVKr5mwDQICIULMrG8wMitQDrJAEJGAdBlWG08Csg2datk7IhZMPY6rtSrIoR2gQAAxYG2rgbDsmUw3B%20DBGXK-oHIiZElKdWzIoUtrD2GcNQPbHhtqEX%20IdTI8YDRPkgHjUUUAU9AlhROnICFQCa1Fs2ayKkf5WRbSYSEF2OaJogDjJkccTCRW5FEe2uiwq2DYBeZbNUvRrgJLPXWi4b8UhMLg5gPW7hB0PSpOWisBsmg4YmlCRNv6wSlOEGc-%20miT1LvuXQAV66HVsP6Nu3dih90Gx8unChdHw0KpkdetmHQH3VvI7EDZ15hAIhk15L9P9AgSYqE3I9wHRyHI0OBv9BhNXoaSAhv1xGwQetQzWfTvQsPaY%20rqphFbCMCdBaAa5yJNXoGdd6xQCB0zTmNQIaNynwR4bORcoVLnbnnrIVKqhMr1JQD-sxvurGOG2A49MmQsyD32pARQojtaHpMI8xIuNEaZHhbc-W1Wls2CVVyNOUpogAsULZQKossqeV8vZfKhNxksy1fSVqvDihfXBua-y2I3L4udaY8KmG4J0PieM5J0S2rh2smHZ%20iFM7o4WCFfxxLm62Ope4ZxjLdr0s5YsIu-1rs7AH16Og2ELIlg2hZFPSgxkFsZkCyADZVJwL-f%205bb9SmlsVAA0B-IGmwM-YQHcFQAqLOYEM6N-Lf6UPIHMyQpIVnAuiGCxiAlMi8vPteE1qtgmKHlYqCN4E06fNGsoAIfzZzlrzsNpYBA9Qax3PbMS4MPRyrQcGOlzL3Gj3NfUZ-NHJmoA0Eboj-w%20sbvyPe-z0lABeLXlKYnci4rBxbMvJMjrHROy2UB83xB%20zgEtam7MEeJ45y9IBqfuaq-T4BKv3UDOdPiUQHimeTMUKzCnTmXc3Iq7TyHOCGfNbdTTqJvuhlM%205KIKd5zdu0eu7z2I6uejA3NURDdSot3HdCHus7WWLu8au6ep3Qn7u%20Tz-er7T660NqbcDxTkUjcqZ4-3dToGtOw-h4r89BnEM-Yx2h7Hlnldg-BFRrMyg5dWC98cqclBm%20zC1xrnXQzU9B5APZx3JXKfOYjxUIrltvOe7jwGhPVTBmzH9zsPzR%20Q-ntK1Ty-6Ao839j2dgfz-0TzmGTwEEP2oywR8CAA.

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

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

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

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

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

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

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

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

要么我的方法是错误的,并且有人可以找到更好的算法来执行相同的操作,这不需要迭代数组(除了data and indata表达式) - 或者这是 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"
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Vega JS中实现树节点切换? 的相关文章

随机推荐

  • 在使用像数组这样的变量之前分配 array()

    我试图找到一个合适的解释性标题 但我找不到 我将尝试解释我在这里问的问题 通常 如果您不将空数组分配给变量 则可以开始为索引分配值 如下所示 hello world Hello World echo hello world 但我总是遇到这样
  • 从工作线程使用 Flask SQLAlchemy

    我有一个 python 应用程序使用烧瓶宁静 http flask restful cn readthedocs io en 0 3 5也Flask SQLAlchemy http flask sqlalchemy pocoo org 2
  • Bootstrap 中缺少可见-** 和隐藏-**

    在Bootstrap v3中我经常使用hidden 类结合clearfix来控制不同屏幕宽度下的多列布局 例如 我可以在一个 DIV 中组合多个 hide 以使我的多列在不同的屏幕宽度下正确显示 举个例子 如果我想显示多行产品照片 在较大的
  • Common Lisp:如何使用条件拼接在宏中构建列表?

    我们假设 defmacro testing optional var list this is when consp var a list 当被调用时 gt testing 2 THIS IS gt testing list 1 2 THI
  • 从 asp.net/C# 查询 MUMPS

    有谁知道如何使用 C 从 MUMPS 数据库查询而不使用 KBSQL ODBC 我们需要从 MUMPS 数据库 Mckesson STAR Patient care 进行查询 当我们使用 KBSQL 时 它仅限于 6 个并发用户 因此我们尝
  • 如何回收/重用 CUDA 线程

    在 CUDA 中 如何为内核中的所有线程创建一个等待的屏障 直到CPU向该障碍发送一个信号 表明继续进行是安全的 有帮助的 我想避免启动 CUDA 内核的开销 有两种类型的开销需要避免 1 在 X 块和 Y 线程上简单启动内核的成本 以及
  • 如何在角度4中以动态形式设置ngIf动态条件

    我正在创建一个动态表单 在其中根据 JSON 的响应动态填充字段 Eg type text required true minlength 3 maxlength 5 name fname visibility true type text
  • 有没有办法使用 HashWithIn DifferentAccess 序列化 ActiveRecord 的 JSON 属性?

    我在用ActiveRecord ConnectionAdapters PostgreSQLAdapter在 Rails 应用程序中 假设我有一个架构 create table foo id bigserial force cascade d
  • 如果未发送,请重试发送邮件

    我正在使用 nodemailer 通过我的节点应用程序发送电子邮件 有时电子邮件不起作用并抛出错误 直到我尝试两次或三次 我希望我的程序一次又一次地尝试 直到邮件成功发送 这是我的代码 const mailOptions from from
  • Django 锁定身份验证 - 登录表单不起作用

    我一直在研究锁定整个页面的方法 一位同事引起了我的注意Django 锁定 https bitbucket org carljm django lockdown src 我已经安装了 我的代码如下所示 INSTALLED APPS lockd
  • jQuery 如何获取元素的边距和填充?

    只是想知道 如何使用 jQuery 我可以获得格式化的总填充和边距等元素 即 30px 30px 30px 30px 或 30px 5px 15px 30px 等 I tried var margT jQuery img css margi
  • StreamingFileSink 未将数据提取到 s3

    我创建了简单的摄取服务 该服务选择本地文件并使用 StreamingFileSink 摄取到 s3 https ci apache org projects flink flink docs stable dev connectors st
  • Java 的快速超越/三角函数

    由于 java lang Math 中的三角函数非常慢 是否有一个库可以快速且良好地近似 似乎可以在不损失太多精度的情况下以数倍的速度进行计算 在我的机器上 乘法需要 1 5ns 而 java lang Math sin 需要 46ns 到
  • 在开始/结束日期将记录拆分为多个记录

    我正在寻找一种解决方案 必须使用另一个表中的数据从一个记录创建一组记录 表定义 DECLARE A AS TABLE AID BIGINT NOT NULL StartDate DATETIME NOT NULL EndDate DATET
  • 如何用SASS将数字转换为百分比? [复制]

    这个问题在这里已经有答案了 我有一张 930 像素 x 530 像素的地图 我想使用 mixin 将纬度 经度坐标转换为框内的顶部 左侧百分比值 这就是我到目前为止所拥有的 mixin latLong lat long left long
  • 使用 PHP 检测日历事件重叠冲突

    我正在开发一项功能 用于检查外部事件是否与内部事件 在日历应用程序中 发生冲突 该过程如下所示 我的应用程序创建了一系列可能的事件 称为 internalEvents 我从 Google Calendar iCloud 等日历 称为 ext
  • 如何捕获或收听浏览器通知?

    我想在 chrome 浏览器上收听 google facebook whatsapp 等网站的传入通知 我看到黑客提到here https stackoverflow com questions 15949606 how can i lis
  • Jquery Tablesorter,按链接url而不是链接内容排序

    我在一个表上使用 Tablesorter 该表使用第一列 共 4 列 中的链接 问题是 在 FF 和 Chrome 中 当通过 url 单击时 它会排序第一列 而不是链接的内容 例如 tr td a href http abc com zz
  • 在proguard中,保存包/默认访问变量和方法的关键字是什么?

    你可以说 keepclassmembers class sun public protected 但我并不排除包 默认访问方法 void myMethod 您可以添加另一个 keepclassmembers像那样 keepclassmemb
  • 如何在Vega JS中实现树节点切换?

    我在用着Vega JS https vega github io vega用于构建树形图 总的来说 我的问题如下 Vega 文档有很棒的树形布局示例 https vega github io vega examples tree layou