如何在 d3.js 中创建家谱?

Posted

技术标签:

【中文标题】如何在 d3.js 中创建家谱?【英文标题】:How do you create a family tree in d3.js? 【发布时间】:2015-09-23 14:15:38 【问题描述】:

我目前正在做一个小型家谱实验,并想实现一个简单的家谱,如下图所示。

到目前为止,最好的搜索结果只产生了一个子节点只能有一个父节点的例子。但我需要的是在实体之间创建链接(从父亲到母亲)以及在节点和其他链接之间创建链接(从孩子到父亲-母亲链接)的能力。 目前我没有固定的数据架构。

我为此because it looks like would be capable of doing the job 选择了d3.js。我只是不知道如何开始,甚至不知道从哪里开始。关于 d3.js 的教程仅涵盖条形图等标准图表。

我希望有人可以帮助我。

【问题讨论】:

一个标准的层次表就可以了..你试过什么? 这里有两个问题:创建和渲染族谱图。 D3.js 是关于渲染的。您需要一个图形数据结构来保存数据。 嗨@prc322 我不确定你是否可以在这里直接帮助你。但在我的项目 (arda-maps.org/familytree) 中,我遇到了同样的麻烦。首先,是的,没有可用于 D3 的开箱即用的家谱布局。所以我一直在寻找一个好的替代品。但不幸的是,没有。也许力布局对你来说也是一个好方法。我认为它肯定不是最好的,但至少它显示了所有需要的连接。随意单击 Show All 按钮以了解大约 400 个节点的外观。 =) 希望对您有所帮助。 你可以看看dagre-d3。它基本上是一个绘制 DAG(有向无环图)的库。因此,您应该也可以使用它来绘制家谱。 Here 是 dagre-d3 图的示例。 我联系了原作者。如果他在 6 天内没有回复,我仍然可以提供答案,但我希望他这样做是因为他应得的。无论如何:不客气! 【参考方案1】:

我的方法如下:

让我们以您在附图中说明的示例:

Jenny Of Oldstones 也是 Aegon V 的孩子,但这个孩子与 Aegon V 的其他孩子之间的区别在于,在这种情况下,我没有画之间的联系。

这是通过在节点 JSON 中将节点设置为 no_parent: true 来完成的 示例:

//Here Q will not have a parent
 
            name: "Q",
            id: 16,
            no_parent: true
 

在代码中检查_elbow 函数_它的作用是不在它和它的父级之间画线:

if (d.target.no_parent) 
    return "M0,0L0,0";

下一个场景是节点Aerys II 和 Rahella 之间的链接这个节点有它的一组子节点。

我在它们之间创建了一个节点,标记为hidden: true, 我为此类节点创建了display:none。孩子们似乎来自节点 Aerys II 和 Rahella 之间的线

JSON 示例:

//this node will not be displayed
 name: "",
    id: 2,
    no_parent: true,
    hidden: true,
    children: [....]

    

在代码中检查我制作矩形的地方,下面的代码隐藏了节点:

    .attr("display", function (d) 
    if (d.hidden) 
        return "none"
     else 
        return ""
    ;
)

完整代码在这里: http://jsfiddle.net/cyril123/0vbtvoon/22/

在上面的示例中,我使用了节点名称 A/B/C... 但您可以根据需要更改它。您需要将文本居中。

我在代码中添加了 cmets 以帮助您理解流程。 万一您对任何一点不清楚,请发表评论,我很乐意澄清。

【讨论】:

如果您观看原始问题中的 cmets,那么您会发现有人链接了我想标记为正确的答案。我改变了主意:你的答案是最好的答案,因为它确实考虑了一些其他人没有考虑的问题。谢谢! @prc322 是的,在为这个答案编码之前,我已经通过了这些 cmets。 @Cyril - 出色的答案。但是,如果您必须支持多个合作伙伴怎么办。例如,如果在您的示例中,假设“Q”有另一个名为“Z”的伙伴并且他们有一个儿子。这会改变结构的方式,对吧? @Cyril - 我调整了结构并在这里发布了一个问题:***.com/questions/34077696/… 首先感谢这种方法。您是否考虑过是否存在交叉(在我的情况下是指植物)之间是否存在超过一代的交叉,例如两个父代之间,一个来自第一代,另一个来自第三代。在某些情况下,当孩子在低代父母之后附加时,您的方法会起作用。但在某些情况下,上一代父代被绘制在较低的 x 方向上,并且图形不合适。任何帮助表示赞赏。【参考方案2】:

dTree 是一个建立在 D3 之上的开源库,用于创建家族树(或类似的层次图)。

它处理了手动生成 D3 图的麻烦部分,并使用简单的 json 数据格式:

[
  name: "Father",
  marriages: [
    spouse: 
      name: "Mother",
    ,
    children: [
      name: "Child",
    ]
  ]
]

如果您有兴趣修改它,它支持节点渲染和事件处理程序的回调。最后,该库截至 2016 年正在开发中,欢迎提出拉取请求。

免责声明:我是 dTree 的作者。我像你一样在网上搜索后创建了这个库,但没有找到任何我喜欢的东西。

【讨论】:

这太棒了,感谢分享,我只是在玩弄创建自己的家谱的想法,这非常有帮助 感谢分享!如果可以选择水平或垂直渲染树,那就太好了! 谢谢你,正是我要找的。​​span> 【参考方案3】:

不太好的消息:我所做的研究表明,没有开箱即用的 d3 库可以直接完成此任务而无需进行一些自定义。

好消息已经有其他人对此进行了研究并找到了一些很好的起点!我意识到这不是手头整个任务的完整解决方案,但是从您的问题看来,到目前为止,您的大部分困难只是弄清楚从哪里开始(例如“关于 d3.js 的教程仅涵盖标准条形图之类的图表。”)。在没有更好的情况下,我至少会在这里回应那部分。

首先,在几年前对this related *** post 的回复中,inanutshellus 提供了一些出色的 d3 工具,这些工具可用并可以在这里使用。通过一些轻量级的自定义/扩展,它们应该能够让您相对快速地到达目的地。为了后代,这里转载了inanutshellus的答案:

有一些选项,但我相信每个选项都需要一点 工作。如果有一个单一的标准来代表 JSON 格式的家谱。我最近注意到 geni.com 有一个相当 对此的深入API。也许针对他们的 API 进行编码将是 可重用性的好主意...

-- 谱系树--

The Pedigree Tree 可能足以满足您的需求。你会让in-law的可链接, 如果你点击他们的名字,图表会重绘,这样你就可以 看看他们的血统。

-- 括号布局树--

类似于谱系树,但是是双向的,这个Bracket Layout Tree 让您处理“这里是我的父母、祖父母、孩子、 孙子”类型的视图。就像谱系树一样,你会做 可链接的个人以在该节点上重新居中括号。

-- 基于力的布局--

有一些有趣的基于力的布局看起来很有希望。 看看this example of a force-based layout with smart labels。一项调整 如何确定“力”的算法可以使其成为 非常可爱的树,老一代高于或低于新一代。

-- 聚类树状图(失败的原因)--

我见过的最适合家庭使用的 d3.js 布局 树假设单个节点是父节点,而您需要 将父母表示为(视觉上是“T”之间的组合) 两个节点:一个节点是树的成员,一个是浮动的 代表姻亲的节点。调整一个聚类树状图来做 这应该是可行的,但并非没有重大修改。

如果您 - 或其他任何人 - 解决这个问题,请告诉我。 ID 喜欢看到(并从中受益)这项工作,并且可能能够做出贡献 可行的话就去吧。

在具体实现方面,mj8591 向this question 询问了一个类似的家谱,但有不同的问题。但是,幸运的是,该问题包含一个小提琴(所有 js 代码),其中包含您需要的大部分或所有组件,response from mdml 包含另一个小提琴,它为每个节点添加了一些更精细的“可点击性”。

再说一遍,这不是自动的,但希望这些资源足以让您有一个良好的开端!

【讨论】:

【参考方案4】:

我试过dtree 并喜欢它。但是,当您添加几代时,水平显示会使整体显示非常大且笨拙。相反,我使用了Reingold–Tilford Tree。这棵树的一个缺点是每个节点只能有一个父节点:配偶不能并排显示:为了克服这个限制,我在发送之前调整了 JSON 以将配偶合并为一个实体(例如:“丈夫 - 妻子”)它到树上。

【讨论】:

【参考方案5】:

问题 3 年后回答。

现在有一个来自 Mike 的谱系树图

https://bl.ocks.org/mell0kat/5cb91a2048384560dfa8f041fd9a0295

然后是这个 d3.tree - 家谱 https://bl.ocks.org/mell0kat/5cb91a2048384560dfa8f041fd9a0295

您也可以再次尝试 Mike 的 D3 Tidy Tree https://beta.observablehq.com/@mbostock/d3-tidy-tree

【讨论】:

你的例子的问题是每个孩子只有一个父母。这可以通过 D3 轻松完成(或者更简单的 google 组织结构图),但问题是它无法显示 2 个父母。【参考方案6】:

您可以使用dTree(基于D3)来实现您的要求。

演示:https://treehouse.gartner.io/ErikGartner/58e58be650453b6d49d7

参考链接:https://github.com/ErikGartner/dTree

【讨论】:

【参考方案7】:

我不知道这是否对您有任何帮助,因为您说过您将使用 d3.js,但您可能还想研究使用另一个名为 jsplumb 的工具。它似乎非常适合这种项目:home page。他们也有一些不错的教程。有one more like docs,还有another more interactive。

就像我说的,如果现在切换技术还不算太晚,那么这可能值得一试。都是 html、css 和 javascript,所以过渡应该不会很苛刻。

【讨论】:

建议更换工具不是答案 当然,如果使用其他工具可以更容易地解决该解决方案,建议其他工具也很有用。严格来说,高投票的答案“dTree”也是另一个工具。建立在 d3 的基础上,但仍然是另一个工具......此外,这个问题以某种方式提出,d3 只是“似乎”是“研究”工作的最佳工具

以上是关于如何在 d3.js 中创建家谱?的主要内容,如果未能解决你的问题,请参考以下文章

在 D3.js 中创建带有序数刻度的文本标记 x 轴

我可以使用d3.js在Android应用程序中创建交互式可视化吗?

d3.js 如何在条形图中添加线条

如何在 d3.js 中为颜色图例添加刻​​度线

如何在 R 中创建单个分支实体/死胡同的外部叶子列表?

在javascript中创建趋势图的库[关闭]