首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在D3.js中改变径向树的根

问如何在D3.js中改变径向树的根
EN

Stack Overflow用户
提问于 2016-04-26 12:29:10
回答 1查看 1.3K关注 0票数 1

我在D3.js中的径向树有问题

我想把选定的节点(点击)放在径向树的中心,让整个树重新适应这个新的设置。在我的更新函数中,我可以将根设置为选定的节点:

代码语言:javascript
复制
root = source; 

但是,这只显示了所选节点和子节点,但我希望父节点(及其子节点)位于所选节点的顶部,而选择节点的子节点位于其底部。

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

代码语言:javascript
复制
var index = source.parent.children.indexOf(source);
source.parent.children.splice(0, 1);
source.parent.parent = source;
source.children.push(source.parent);

全码这里

如果有任何帮助或指示,我将不胜感激。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-26 13:07:17

下面是一个负责重排的递归函数:

代码语言:javascript
复制
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
}

我不知道如何迫使原始节点的子节点被吸引到南部,其余的被吸引到北方。首先要做的是知道每个节点必须位于哪一边(这很简单:默认情况下,所有节点都是“北方”的,然后在调用makeRoot之前从makeRoot访问子树,并告诉它们为"south")。但在那之后,我对d3的树布局还不太熟悉,无法执行“北/南”约束。

更新用于南北方向,您可以尝试以下操作:

  • 保持指向所选节点的原始父节点的指针oldParent=source.parent
  • 布局完成后,在更新svg之前,计算offsetX= 90- oldParent.x (父轴和北轴之间的差异-- NB:我不确定北轴是90°,但应该是0、90、180或270之一)。试试看吧;)
  • 通过一定量的offsetX (保持角度在0到359之间)移动所有节点: Nodes.forEach(函数(D){ d.x = (d.x + offsetX) % 360;});
  • 然后你可以更新svg:整棵树应该被旋转,这样原始的父节点指向北.这应该足以达到你想要的视觉效果。

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

见Fiddle这里:https://jsfiddle.net/qo4w0ktn/4/

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

代码语言:javascript
复制
  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
    });  
  }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36864983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档