d3.js 将d3层次结构(d3树)图反转到左侧,以便也显示下游

liwlm1x9  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(228)

我有两组数据,一组用于上游,一组用于下游。上游和下游都有相同的主节点John。

上游数据

var upstreamData = [
  { name: "John", parent: "" },
  { name: "Ann", parent: "John" },
  { name: "Adam", parent: "John" },
  { name: "Chris", parent: "John" },
  { name: "Tina", parent: "Ann" },
  { name: "Sam", parent: "Ann" },
  { name: "Rock", parent: "Chris" },
  { name: "will", parent: "Chris" },
  { name: "Nathan", parent: "Adam" },
  { name: "Roger", parent: "Tina" },
  { name: "Dena", parent: "Tina" },
  { name: "Jim", parent: "Dena" },
  { name: "Liza", parent: "Nathan" }
];

下游数据

var downstreamData = [
  { name: "John", parent: "" },
  { name: "Kat", parent: "John" },
  { name: "Amily", parent: "John" },
  { name: "Summer", parent: "John" },
  { name: "Loki", parent: "Kat" },
  { name: "Liam", parent: "Kat" },
  { name: "Tom", parent: "Amily" }
];

我能够使用d3层次结构和d3树将上游数据表示到主节点的右侧,下图为

如何将下游数据表示到主节点John的左侧,以便在同一图中同时看到John的上游和下游数据?
下面是我的codesandbox的链接
https://codesandbox.io/s/d3-practice-forked-y69kkw?file=/src/index.js
提前感谢!

waxmsbnn

waxmsbnn1#

我对这个问题的答案进行了调整,使其适合您的数据结构。
该方法具有关键步骤:
1.* 请记住,对于水平布局,您需要翻转xy ...*
1.计算上游和下游的树布局
1.使根节点具有相同的xy
1.重新计算每个节点的y坐标,使得根位于中心,下游分支向左工作,上游分支向右工作。
1.绘制两棵树
如果您跳过步骤3,则会得到以下结果(其中红色表示上游,绿色表示下游):

因此,将其翻转,使下游树在左侧,上游树在右侧(且根居中):

  • 我们需要将上游节点的y坐标(即它的x)减半,并加上innerWidth的一半,对于根节点,这将放在中间,但对于后代节点,它将按比例放在右手边:
Array.from(nodesUpstream).forEach(n => n.y = (n.y * 0.5) + innerWidth / 2);

然后,对下游节点y的坐标(实际上是x ......)执行相同的减半操作,但*-1会“镜像”它们,然后将innerWidth / 2添加回来。根节点仍将位于中心,但现在后代节点按比例位于左手并进行镜像

Array.from(nodesDownstream).forEach(n => n.y = ((n.y * 0.5) * -1) + innerWidth / 2);

请参阅以下包含OP数据的工作片段:
第一个
结果是:

有两个限制:根被画了两次(我猜你可以跳过其中一次的John标签),更重要的是,在重新布局y坐标时,树的深度没有被考虑。如果你有一个更深的上游树,你会看到这个,因为它仍然会被布局在右边的一半,而且会更“紧缩”。

编辑

若要固定节点宽度(根据深度),则可以使用以下命令:

const depthFactor = 60;
Array.from(nodesUpstream).forEach(n => n.y = (n.depth * depthFactor) + innerWidth / 2);
Array.from(nodesDownstream).forEach(n => n.y = (innerWidth / 2) - (n.depth * depthFactor));

示例:
第一个
其给出:

相关问题