我在D3.js中的放射状树有问题

我想将选定的节点(单击)放在放射状树的中心,并使整个树重新适应此新设置。在更新功能中,我可以将根设置为所选节点:

root = source;


但是,这仅显示选定的节点和子节点,但是我希望将父节点(及其子节点)置于选定节点的顶部,并将选定节点的子节点置于其底部。

我试过的是从父级的子级数组中删除选定的节点。然后将此更改后的父项作为所选节点的子项进行推送,但这会产生递归错误。

var index = source.parent.children.indexOf(source);
source.parent.children.splice(0, 1);
source.parent.parent = source;
source.children.push(source.parent);


完整代码here

我将不胜感激任何帮助或指示。

谢谢

最佳答案

这是一个处理重排的递归函数:

function makeRoot(source) {
   if (!source.parent) return; //nothing to do if source is already root

   makeRoot(source.parent); //flip the higher branches recursively so that the parent becomes root of the tree

   var index = source.parent.children.indexOf(source);
   source.parent.children.splice(index, 1);  //corrected here: you need to remove the right element from the children list
   source.parent.parent = source;
   source.children.push(source.parent);
   delete source.parent; //added: now that the original parent is linked, make source the root of the tree
}


我不确定如何强制将原始节点的子项吸引到南部,将其余部分吸引到北部。首先要做的是知道每个节点必须在哪一侧(这很容易:默认情况下,所有节点都是“北”,然后在调用source之前访问makeRoot的子树,并告诉它们是“南”)。但是在那之后,我对d3中的树布局还不够熟悉,无法执行“北/南”约束。



如果您要更新南北方向,可以尝试以下方法:


保持指向所选节点的原始父级的指针oldParent=source.parent
一旦完成布局,并在更新svg之前,计算offsetX= 90- oldParent.x(父位置和北轴之间的差值-NB:我不确定北轴是否为90°,但应为0之一) ,90、180或270 ..只需全部尝试;))
将所有节点移位offsetX的角度(保持角度在0到359之间):

nodes.forEach(function(d) {
    d.x = (d.x + offsetX) % 360;
});

那么您可以更新svg:应该旋转整棵树,以使原始父节点指向北...这应该足以获得所需的视觉效果。




更新#2另一种使南北对齐的方法。

请参阅此处的小提琴:https://jsfiddle.net/qo4w0ktn/4/

这个想法是要计算原始孩子之间最左边和最右边的叶子的角度,然后旋转整个图,直到这两个角度的平均值指向南。这意味着您需要跟踪树中的“原始”孩子,这是通过我的d.real_children属性完成的。函数leftmostLeafrightmostLeaf很简单(请参见小提琴)。

  function rotateSouth(source, nodes) {
    var lx = leftmostLeaf(source);
    var rx = rightmostLeaf(source);

    if (lx>rx) rx += 360; //this happens if the interval overlap angle 0

    var offsetX= 180- (lx+rx)/2; //the median point (=(lx+rx)/2) should be pushed south (=180)

    nodes.forEach(function(d) {
      d.x = (d.x + offsetX) % 360; //rotate every node by the same offset
    });
  }

07-26 07:57