在 d3.js v4 中以编程方式打开嵌套、折叠(隐藏)节点 [英] Programmatically open nested, collapsed (hidden) nodes in d3.js v4

查看:17
本文介绍了在 d3.js v4 中以编程方式打开嵌套、折叠(隐藏)节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试以编程方式打开可折叠树中的 d3.js 节点:

我使用以下 d3.js 代码段加载数据(在第二级之后折叠节点),

d3.json("js/ontology.json", function(error, treeData) {如果(错误)抛出错误;root = d3.hierarchy(treeData, function(d) { return d.children; });root.x0 = 高度/2;根.y0 = 0;//在第二级之后折叠:root.children.forEach(折叠);更新(根);});

然后我使用以下 d3.js 代码

var nodeEnter = node.enter().append('g').attr('类', '节点').attr('节点名称', d => d.data.name.toLowerCase()).attr(转换",函数(d){return "translate(" + source.y0 + "," + source.x0 + ")";}).on('点击', 点击);

还有这个功能

function expandNode() {const node = d3.select('.node[node-name="Nature"]').node();console.log('节点:', 节点);node.dispatchEvent(new Event('click'));}展开节点();

以编程方式打开自然"节点.

然而,当我替换自然"时(可见节点)与地球"(自然"的嵌套子代,不可见)这个表达式

const node = d3.select('.node[node-name="Earth"]').node();

将扩大地球"仅当节点可见时.

该声明不会扩展自然";显示地球"(并随后扩展地球")如果地球"不可见.

建议?


编辑 1.这与我之前的 StackOverflow 问题密切相关,

以编程方式打开 d3.js v4 可折叠树节点?

如果需要,请参考那里引用的 JSFiddle,

https://jsfiddle.net/vstuart/acx5zfgn/62/

标签不同,但数据和代码相似.


编辑 2. 后续问题

在 d3 中访问承诺的数据.js v6 [以编程方式打开嵌套的折叠节点]

关于:

  • d3.js v6;
  • 通过 d3.js 回调/promise 加载外部 JSON 数据;
  • 这个问题,在更新的上下文中.

本体.json

{ "name": "Root",儿童":[{名称":文化",儿童":[{姓名":LGBT";}]},{名称":自然",id":性质",儿童":[{名称":地球",id":地球",儿童":[{名称":环境";},{名称":地理"},{名称":地质";},{名称":地缘政治";},{名称":地缘政治 - 国家";},{ 名称":地缘政治 - 国家 - 加拿大"},{名称":地缘政治 - 国家 - 美国"},{名称":自然";},{名称":区域";}]},{名称":宇宙"},{名称":外太空"}]},{名称":人文",儿童":[{名称":历史";},{名称":哲学";},{名称":哲学-神学";}]},{名称":杂项",儿童":[{名称":维基百科",网址":https://wikipedia.com"},{名称":Example.com",网址":https://example.com"}]},{名称":科学",儿童":[{名称":生物学"},{名称":健康";},{名称":健康-医学";},{名称":社会学";}]},{名称":技术",儿童":[{名称":计算机";},{ 名称":计算机 - 硬件"},{ 名称":计算机 - 软件"},{名称":计算";},{ 名称":计算 - 编程";},{名称":互联网"},{名称":空格";},{名称":运输";}]},{名称":社会",儿童":[{名称":业务";},{名称":经济学";},{ 名称":经济 - 商业"},{名称":经济 - 资本主义";},{名称":经济 - 商务";},{名称":经济-金融"},{名称":政治";},{名称":公共服务";}]}]}

解决方案

您需要递归地发现节点祖先,然后将它们逐一展开:

const findNodeAncestors = (root, name) =>{如果(root.name === 名称){返回 [名称];}如果(root.children){for (让 i = 0; i < root.children.length; i++) {const chain = findNodeAncestors(root.children[i], name);如果(链){chain.push(root.name);返回链;}}}返回空;};const chain = findNodeAncestors(treeData.data, '地球');for (let i = chain.length - 1; i >= 0; i--) {const node = d3.select(`.node[node-name="${chain[i]}"]`);const nodeData = node.datum();if (!nodeData.children && nodeData.data.children) {//节点有子节点并折叠node.node().dispatchEvent(new Event('click'));//展开节点}}

查看它在 fiddle 中的工作.

I am trying to programmatically open d3.js nodes in a collapsible tree:

I load the data with the following d3.js snippet (which collapses the nodes after the second level),

d3.json("js/ontology.json", function(error, treeData) {
  if (error) throw error;
  root = d3.hierarchy(treeData, function(d) { return d.children; });
  root.x0 = height / 2;
  root.y0 = 0;
  // Collapse after the second level:
  root.children.forEach(collapse);
  update(root);
});

I then use the following d3.js code

var nodeEnter = node.enter().append('g')
    .attr('class', 'node')
    .attr('node-name', d => d.data.name.toLowerCase())
    .attr("transform", function(d) {
      return "translate(" + source.y0 + "," + source.x0 + ")";
  })
.on('click', click);

and this function

function expandNode() {
  const node = d3.select('.node[node-name="Nature"]').node();
  console.log('NODE: ', node);
  node.dispatchEvent(new Event('click'));
  }
expandNode();

to programmatically open the "Nature" node.

However, when I substitute "Nature" (visible node) with "Earth" (nested child of "Nature", not visible) this expression

const node = d3.select('.node[node-name="Earth"]').node();

will expand the "Earth" node only if it is visible.

That statement will not expand "Nature" to show "Earth" (and subsequently expand "Earth") if "Earth" is not visible.

Suggestions?


Edit 1. This is closely related to my earlier StackOverflow question,

Programmatically opening d3.js v4 collapsible tree nodes?

If needed, please refer to the JSFiddle referenced there,

https://jsfiddle.net/vstuart/acx5zfgn/62/

The labels are different but otherwise the data and code are similar.


Edit 2. Follow-on question

Accessing promised data in d3.js v6 [programmatically opening nested collapsed nodes]

relating to:

  • d3.js v6;
  • loading external JSON data via d3.js callback/promise;
  • this question, in that updated context.

ontology.json

{ "name": "Root",
  "children": [
    { "name": "Culture",
      "children": [
        { "name": "LGBT" }
      ]
    },

    { "name": "Nature",
      "id": "nature",
      "children": [
        { "name": "Earth",
          "id": "earth",
          "children": [
            { "name": "Environment" },
            { "name": "Geography" },
            { "name": "Geology" },
            { "name": "Geopolitical" },
            { "name": "Geopolitical - Countries" },
            { "name": "Geopolitical - Countries - Canada" },
            { "name": "Geopolitical - Countries - United States" },
            { "name": "Nature" },
            { "name": "Regions" }
          ]
        },
        { "name": "Cosmos" },
        { "name": "Outer space" }
      ]
    },

    { "name": "Humanities",
      "children": [
          { "name": "History" },
          { "name": "Philosophy" },
          { "name": "Philosophy - Theology" }
      ]
    },

    { "name": "Miscellaneous",
      "children": [
          { "name": "Wikipedia",
            "url": "https://wikipedia.com" },
          { "name": "Example.com",
            "url": "https://example.com" }
      ]
    },
      
    { "name": "Science",
      "children": [
          { "name": "Biology" },
          { "name": "Health" },
          { "name": "Health - Medicine" },
          { "name": "Sociology" }
      ]
    },

    { "name": "Technology",
      "children": [
            { "name": "Computers" },
            { "name": "Computers - Hardware" },
            { "name": "Computers - Software" },
            { "name": "Computing" },
            { "name": "Computing - Programming" },
            { "name": "Internet" },
            { "name": "Space" },
          { "name": "Transportation" }
      ]
    },

  { "name": "Society",
      "children": [
            { "name": "Business" },
            { "name": "Economics" },
            { "name": "Economics - Business" },
            { "name": "Economics - Capitalism" },
            { "name": "Economics - Commerce" },
            { "name": "Economics - Finance" },
            { "name": "Politics" },
          { "name": "Public services" }
      ]
    }
  ]
}

解决方案

You need to discover the node ancestors recursively and then expand them on by one:

const findNodeAncestors = (root, name) => {
  if (root.name === name) {
    return [name];
  }

  if (root.children) {
    for (let i = 0; i < root.children.length; i++) {
      const chain = findNodeAncestors(root.children[i], name);
      if (chain) {
        chain.push(root.name);
        return chain;
      }
    }
  }
  return null;
}; 
   

const chain = findNodeAncestors(treeData.data, 'Earth');
  
for (let i = chain.length - 1; i >= 0; i--) {
  const node = d3.select(`.node[node-name="${chain[i]}"]`);
  const nodeData = node.datum();
  if (!nodeData.children && nodeData.data.children) {  // Node has children and collapsed
    node.node().dispatchEvent(new Event('click'));     // Expand the node
  }
}

See it's working in a fiddle.

这篇关于在 d3.js v4 中以编程方式打开嵌套、折叠(隐藏)节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆