Javascript d3:节点+;建立多代家谱的链接;如何解析数据以绘制线?

Javascript d3:节点+;建立多代家谱的链接;如何解析数据以绘制线?,javascript,d3.js,Javascript,D3.js,我正在d3.js中制作一个三到四代的家谱。您可以在此处看到早期版本: 代码: //人 变量节点=[ {id:1,姓名:“亚伦”,x:50,y:100,性别:“男性”,出生日期:“1900”,父母:假,父母:真,配偶1_id:2}, {id:2,姓名:“布丽娜”,x:400,y:100,性别:“女性”,出生日期:“1900”,父母:假,父母:真,配偶1_id:1}, {id:3,姓名:“Caden”,x:100,y:260,性别:“女性”,dob:“1925”,haspaunt:true,par

我正在d3.js中制作一个三到四代的家谱。您可以在此处看到早期版本:

代码:

//人
变量节点=[
{id:1,姓名:“亚伦”,x:50,y:100,性别:“男性”,出生日期:“1900”,父母:假,父母:真,配偶1_id:2},
{id:2,姓名:“布丽娜”,x:400,y:100,性别:“女性”,出生日期:“1900”,父母:假,父母:真,配偶1_id:1},
{id:3,姓名:“Caden”,x:100,y:260,性别:“女性”,dob:“1925”,haspaunt:true,parent1\u id:1,parent2\u id:2,haspouse:false},
{id:4,姓名:“大卫”,x:200,y:260,性别:“男性”,dob:“1930”,haspaunt:true,parent1\u id:1,parent2\u id:2,haspouse:false},
{id:5,姓名:“Ewa”,x:320,y:260,性别:“女性”,dob:“1935”,haspaunt:true,parent1\u id:1,parent2\u id:2,haspouse:true,配偶id:6},
{id:6,姓名:“Feivel”,x:450,y:260,性别:“男性”,出生日期:“1935”,父母:假,配偶:真,配偶_id:5},
{id:7,姓名:“Gershon”,x:390,y:370,性别:“男性”,dob:“1955”,haspaunt:true,parent1\u id:5,parent2\u id:6,haspouse:false}
];
变量链接=[
{源:0,目标:1}
];
//使视口自动调整为节点的最大X和Y值
var max_x=0;
var max_y=0;
对于(var i=0;i=max_x){max_x=temp_x;}
如果(temp_y>=max_y){max_y=temp_y;}
}
//变数
变量宽度=最大值x,
高度=最大值,
边距={顶部:10,右侧:10,底部:10,左侧:10},
循环率=20,
圆圈行程宽度=3;
//基本设置
var svg=d3.选择(“正文”).追加(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.attr(“id”、“可视化”)
.attr(“xmlns”)http://www.w3.org/2000/svg");
var elem=svg.selectAll(“g”)
.数据(节点)
var elemEnter=elem.enter()
.附加(“g”)
.attr(“数据名”,函数(d){return d.name})
.attr(“数据性别”,函数(d){return d.gender})
.attr(“数据dob”,函数(d){返回d.dob})
//每个节点画一个圆
var circle=elemEnter.append(“circle”)
.attr(“cx”,函数(d){return d.x})
.attr(“cy”,函数(d){return d.y})
.attr(“r”,circleRadius)
.attr(“笔划宽度”,圆圈笔划宽度)
.attr(“类”,函数(d){
性别差异;
如果(d.gender==“female”){returnGender=“circle female”;}
else如果(d.gender==“male”){returnGender=“circle male”}
else{returnGender=“circle”;}
返回性别;
});
//向节点添加文本
elemEnter.append(“文本”)
.attr(“dx”,函数(d){return(d.x+28)})
.attr(“dy”,函数(d){返回d.y-5})
.text(函数(d){返回d.name})
.attr(“类”、“文本”);
//向节点添加文本
elemEnter.append(“文本”)
.attr(“dx”,函数(d){return(d.x+28)})
.attr(“dy”,函数(d){返回d.y+16})
.text(函数(d){返回“b.”+d.dob})
.attr(“类”、“文本”);
//在节点之间添加链接
var linksEls=svg.selectAll(“.link”)
.数据(链接)
.输入()
//绘制第一条线(在主对、节点0和1之间)
.附加(“行”)
.attr(“x1”,函数(d){返回节点[d.source].x+circleRadius+circleStrokeWidth;})
.attr(“y1”,函数(d){返回节点[d.source].y;})
.attr(“x2”,函数(d){返回节点[d.target].x-circleRadius-circleStrokeWidth;})
.attr(“y2”,函数(d){返回节点[d.target].y;})
.attr(“类”、“行”);
//绘制后续线(从每个子对象到夫妇线的中点)
功能抽绳(d){
var x1=节点[d.source].x;
var y1=节点[d.source].y;
var x2=节点[d.target].x;
var y2=节点[d.target].y;
var childNodes=nodes.filter(函数(d){return((d.hasParent==true)&&(d.id!=7));
forEach(函数(childNode){
svg.append(“行”)
//这将从节点*向上*绘制到耦合线的中点
.attr(“x1”,函数(d){return childNode.x;})
.attr(“y1”,函数(d){return childNode.y-circleRadius-circleStrokeWidth+1;})
.attr(“x2”,函数(d){return(x1+x2)/2;})
.attr(“y2”,函数(d){返回(y1+y2)/2;})
.attr(“类别”、“第2行”);
})
}
每个连杆(抽绳);
这对一代人来说很有效。问题是,到了下一代(伊娃嫁给了费维尔,孩子是格肖姆)的时候,我们必须想办法复制一个结构,在伴侣之间有一条直线,从父母夫妇的中间点向下延伸到孩子。一个相关的问题是,目前,第一对被识别为一对(不同的线型),只是因为它们是我节点列表中的前两个数据,而不是通过读取数据(即hasSpouse、spouse1_id等)来真正被识别


我们非常感谢您为使这项工作更好而提出的想法和想法

让所有具有hasSpouse属性值true的人员都具有配偶id(而不是配偶id或配偶id),并从节点数组生成链接数组,如下所示
couple
对象用于防止链接冗余,如0->1和1->0的链接

var couple = {},
    links = [];
nodes.forEach(function(d, i) {
    if (d.hasSpouse) {
        var link = {};
        link["source"] = i;
        var targetIdx;
        nodes.forEach(function(s, sIdx) {
            if (s.id == d.spouse_id) targetIdx = sIdx;
        });
        link["target"] = targetIdx;
        if (!couple[i + "->" + targetIdx] && !couple[targetIdx + "->" + i]) {
            couple[i + "->" + targetIdx] = true;
            links.push(link);
        }
    }
});
现在,您需要在代码中做一些小更改,以便在
drawLines
方法中查找子节点。通过匹配子节点的父ID来查找子节点

function drawLines(d) {
    var src = nodes[d.source];
    var tgt = nodes[d.target];
    var x1 = src.x, y1 = src.y, x2 = tgt.x, y2 = tgt.y;
    var childNodes = nodes.filter(function(d) {
        //Code change
        return ((d.hasParent === true) && (d.parent1_id == src.id && d.parent2_id == tgt.id))
    });
    ......................
}
以下是最新的

function drawLines(d) {
    var src = nodes[d.source];
    var tgt = nodes[d.target];
    var x1 = src.x, y1 = src.y, x2 = tgt.x, y2 = tgt.y;
    var childNodes = nodes.filter(function(d) {
        //Code change
        return ((d.hasParent === true) && (d.parent1_id == src.id && d.parent2_id == tgt.id))
    });
    ......................
}