简体   繁体   English

带有 React 的 D3 可折叠树:不更新节点

[英]D3 collapsible tree with React: not updating nodes

I am using d3 collapsible tree, the code for which I copied from:我正在使用d3可折叠树,我从中复制的代码:

https://bl.ocks.org/mbostock/4339083 https://bl.ocks.org/mbostock/4339083

I am trying to accomodate it for my React web app and change it, so that I could append nodes to any tree nodes myself.我正在尝试将它用于我的React Web 应用程序并对其进行更改,以便我可以自己将节点附加到任何树节点。 It is appending nodes, creating links correctly, except that text at the nodes positions are not changed and the nodes are not collapsing/expanding when clicking on them.它正在附加节点,正确创建链接,除了节点位置的文本未更改并且节点在单击时不会折叠/展开。 So, these are two my main issues that I believe are very related to each other.所以,这是我认为彼此非常相关的两个主要问题。 Here is what I am doing:这是我在做什么:

Inside of componentDidUpdate I am calling the function that is creating and updating the tree chart:componentDidUpdate内部,我正在调用创建和更新树形图的函数:

componentDidUpdate() {
   this.updateGeneTreeChart(this.getRoot());
} 

Update happens when I am selecting (using basic html select ) node value to append next node to, and entering in a text field the value and then hit a button.当我选择(使用基本的 html select )节点值以将下一个节点附加到,并在文本字段中输入该值然后点击按钮时,会发生更新。 So, I set the node to append to and text of the new node.因此,我将节点设置为附加到新节点的文本。

updateGeneTreeChart is: updateGeneTreeChart是:

updateGeneTreeChart = (source) => {
const svg = d3.select(this.node);
//svg.selectAll("*").remove();
const margin = {top: 20, right: 120, bottom: 20, left: 120};
const width = 960 - margin.right - margin.left;
const height = 800 - margin.top - margin.bottom;
let i = 0;
const duration = 750;

let root = this.getRoot();

let tree = d3.layout.tree()
    .size([height, width]);

let diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });

let nodes = tree.nodes(root).reverse(),
    links = tree.links(nodes);
console.log("root.children");
console.log(root);
console.log(root.children);
/*if (this.state.selectedGeneArr.length) {
  root.children.forEach(this.collapse, this);
}*/
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });

// Update the nodes…
let node = svg.selectAll("g.node")
    .data(nodes, function(d) { return d.id || (d.id = ++i); });

// Enter any new nodes at the parent's previous position.
let nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
    .on("click", this.clickNode);

node.attr("text", function(d) {
  return d.name;
});


nodeEnter.append("circle")
    .attr("r", 1e-6)
    .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

nodeEnter.append("text")
    .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
    .attr("dy", ".35em")
    .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
    .text(function(d) { return d.name; })
    .style("fill-opacity", 1e-6);

// Transition nodes to their new position.
let nodeUpdate = node.transition()
    .duration(duration)
    .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

nodeUpdate.select("circle")
    .attr("r", 4.5)
    .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

nodeUpdate.select("text")
    .style("fill-opacity", 1);

// Transition exiting nodes to the parent's new position.
let nodeExit = node.exit().transition()
    .duration(duration)
    .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
    .remove();

nodeExit.select("circle")
    .attr("r", 1e-6);

nodeExit.select("text")
    .style("fill-opacity", 1e-6);

// Update the links…
let link = svg.selectAll("path.link")
    .data(links, function(d) { return d.target.id; });

// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
    .attr("class", "link")
    .attr("d", function(d) {
      var o = {x: source.x0, y: source.y0};
      return diagonal({source: o, target: o});
    });

// Transition links to their new position.
link.transition()
    .duration(duration)
    .attr("d", diagonal);

// Transition exiting nodes to the parent's new position.
link.exit().transition()
    .duration(duration)
    .attr("d", function(d) {
      var o = {x: source.x, y: source.y};
      return diagonal({source: o, target: o});
    })
    .remove();

// Stash the old positions for transition.
nodes.forEach(function(d) {
  d.x0 = d.x;
  d.y0 = d.y;
});
}

getRoot() function is just getting a deep copy of the updated object that I am using to build the tree: getRoot()函数只是获取我用来构建树的更新对象的深层副本:

getRoot = () => {
  const margin = {top: 20, right: 120, bottom: 20, left: 120},
  width = 960 - margin.right - margin.left,
  height = 800 - margin.top - margin.bottom;
  let root = JSON.parse(JSON.stringify(this.state.geneTreeJSON));
  root.x0 = height / 2;
  root.y0 = 0;
  return root;
}

geneTreeJSON is the actual object that I am updating. geneTreeJSON是我正在更新的实际对象。 I am sure that it is updated correctly, that its structure is right, that the nodes object in the updateGeneTreeChart is correct:我确信它被正确更新,它的结构是正确的, updateGeneTreeChart中的nodes对象是正确的:

在此处输入图片说明

However, all the newly attached nodes either have no text or have the text of the root node (in this particular case - Il4ra ).但是,所有新附加的节点要么没有文本,要么具有根节点的文本(在这种特殊情况下 - Il4ra )。 If I delete everything inside of svg at the beginning of each update it actually draws the right text at the nodes.如果我在每次更新开始时删除svg中的所有内容,它实际上会在节点处绘制正确的文本。 So, somehow the text is not updating.所以,不知何故,文本没有更新。 I tried to do the following:我尝试执行以下操作:

node.attr("text", function(d) {
      return d.name;
    });

OR或者

nodeEnter.attr("text", function(d) {
      return d.name;
    });

Not working.不工作。 I tried then to print out what is passed to the nodes:然后我尝试打印出传递给节点的内容:

nodeEnter.append("text")
    .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
    .attr("dy", ".35em")
    .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
    .text(function(d) {
      console.log("nodeEnter");
      console.log(d); 
      return d.name; })
    .style("fill-opacity", 1e-6);

And d is the root node, children are not printed out. d是根节点,子节点没有打印出来。 So, I guess this is where the issue of text at least should be fixed but I do not know how.所以,我想这是至少应该解决文本问题的地方,但我不知道如何解决。 Any suggestions would be greatly appreciated.任何建议将不胜感激。

I was able to fix the text of the nodes by adding the code:我能够通过添加代码来修复节点的文本:

// Update the nodes…
let node = svg.selectAll("g.node")
            .data(nodes, function(d) { return d.id || (d.id = ++i); });

---->    node.select("text")
           .data(nodes)
           .text(function(d) {
                return d.name; });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM