Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 具有相同父节点的d3.js树节点_Javascript_Node.js_D3.js - Fatal编程技术网

Javascript 具有相同父节点的d3.js树节点

Javascript 具有相同父节点的d3.js树节点,javascript,node.js,d3.js,Javascript,Node.js,D3.js,我是D3新手。 因此,我试图呈现一个图,其中两个或更多的子对象可以具有相同的父对象。我想知道如何使链接再次直接指向同一节点?我的链接断了 任何帮助都会很好 这是我的密码 var margin = { top: 100,right: 50,bottom: 200,left: 1360 }, customNodes = new Array(), layer_wider_label = new Array(), label_w = 70, branch_w = 70,

我是D3新手。 因此,我试图呈现一个图,其中两个或更多的子对象可以具有相同的父对象。我想知道如何使链接再次直接指向同一节点?我的链接断了

任何帮助都会很好

这是我的密码

var margin = { top: 100,right: 50,bottom: 200,left: 1360 },
    customNodes = new Array(),
    layer_wider_label = new Array(),
    label_w = 70,
    branch_w = 70,
    m = [100, 500, 100, 500],
    realWidth = window.innerWidth,
    realHeight = window.innerHeight,
    h = realHeight,// -m[0] -m[2],
    w = realWidth,// -m[0] -m[0], 
    width = 3700 - margin.right - margin.left,
    height = 2050 - margin.top - margin.bottom;

    root = (function () {
        var json = null;
        $.ajax({
            'async': false,
            'global': false,
            'url': "/PedigreeImport/json/tree6.json",
            'dataType': "json",
            'success': function (data) {
                json = data;
            }
        });
        return json;
        })(); 

var i = 0,
    duration = 550,
    rectW = 80,
    rectH = 17,
    ms;

var tree = d3.layout.tree().nodeSize([120, 50]);

var diagonal = d3.svg.diagonal()
                 .projection(function (d) {
                    return [d.x + rectW / 2, (height-d.y) + rectH / 2];
                 });

var svg = d3.select("#graphDiv").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("class","drawarea")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


var ms = document.getElementById('maxStep').value;
var tmpNodes = d3.layout.tree().size([450, 300]).nodes(root);
root.x0 = function(d) { return d.x; };//0;
root.y0 = function(d) { return height - d.y; };//height / 2;

root.depth = parseInt(root.layer);
customNodes.push(root);
prepareNodes(root.children);
updateNodesXOffset()

//root.children.forEach(collapse);
update(root);

d3.select("#graphDiv").style("height", "660px");


function collapse(d) 
{
    if (d.children) 
    {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
    }
}

/*d3.select("svg")
  .call(d3.behavior.zoom()
  .scaleExtent([0.5,5])
  .on("zoom", zoom));*/


function updateNodesXOffset(){
var x_offsets = new Array();
x_offsets[0] = 0;
customNodes.forEach(function(node) {
    node.x = 0;
    if (node.layer > 0) {
        node.x = x_offsets[node.layer - 1] + layer_wider_label[node.layer - 1] + branch_w;
        x_offsets[node.layer] = node.x;
    }
});
}

function prepareNodes(nodes) {
nodes.forEach(function(node) {
    //alert('try');
    prepareNode(node);
    if (node.children) {
        prepareNodes(node.children);
    }
});
}

function prepareNode(node) {
node.y = getNodeY(node.id);
    //.on("click", click);
//fake element to calculate labels area width.
var fakeTxtBox = svg.append("svg:text")
        .attr("id", "fakeTXT")
        .attr("text-anchor", "right")
        .text(node.name + " : " + node.gid)
        //.on("click", click(node));
var this_label_w = fakeTxtBox.node().getComputedTextLength();
svg.select("#fakeTXT").remove();
if (layer_wider_label[node.layer] == null) {
    layer_wider_label[node.layer] = this_label_w;
} else {
    if (this_label_w > layer_wider_label[node.layer]) {
        layer_wider_label[node.layer] = this_label_w;
    }
}
//                node.x = nodex;
//x will be set
node.depth = parseInt(node.layer);
customNodes.push(node);
//node.on("click", click(node));
}

function getNodeY(id) {
var ret = 0;
tmpNodes.some(function(node) {
    if (node.id === id) {
        //return x:d3.tree has a vertical layout by default.
        //ret = node.x
        ret = node.x;
        return;
    }
})
return ret;
}

function update(source) 
{
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
    links = tree.links(nodes,function (d) {
        return d.id || (d.id = ++i)
        });

// Normalize for fixed-depth.
nodes.forEach(function (d) {
    d.y = d.depth * 100;
});

// Update the nodes…
var node = svg.selectAll("g.node")
    .data(nodes, function (d) {
        return d.id || (d.id = ++i);
});
//if(node.depth <= ms){
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter()
                    .append("g")
                    .attr("class", "node")
                    .attr("transform", function (d) {
                        return "translate(" + source.x0 + "," + source.y0 + ")";
                    })
                    .on("click", click);

//var txtBox = nodeEnter.append("text")

//var txtW = txtBox.node().getComputedTextLength();
nodeEnter.append("rect","text")
         .attr("width", rectW)
         .attr("height", rectH)
         .attr("stroke", "black")
         .attr("stroke-width", 0.5)
         .attr("rx", 4)
         .attr("ry", 4)
         .style("fill", function (d) {
            return d._children ? "#0099FF" : "#fff";
         });


nodeEnter.append("text")
         .attr("x", rectW / 2)
         .attr("y", rectH / 2)
         .attr("stroke", node.current ? "#ffffff" : node.children ? "#ffffff" : "#000000")
         .attr("stroke-width", 0.5)
         //.attr("stroke", "white")
         .attr("dy", ".15em")
         .attr("text-anchor", "middle")
         .text(function (d) {
            return d.name;
         });


// Transition nodes to their new position.
var nodeUpdate = node.transition()
                     .duration(duration)
                     .attr("transform", function (d) {
                        return "translate(" + d.x + "," + (height-d.y) + ")";
                     });

nodeUpdate.select("rect","text")
          .attr("width", rectW)
          .attr("height", rectH)
          .attr("stroke", "black")
          .attr("stroke-width", 0.5)
          .attr("rx", 4)
          .attr("ry", 4)
          .style("fill", function (d) {
            return d._children ? "#0099FF" : "#fff";
          });

nodeUpdate.select("text")
          .style("fill-opacity", 1);

// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit()
                   .transition()
                   .duration(duration)
                   .attr("transform", function (d) {
                        return "translate(" + source.x + "," + (height-source.y) + ")";
                   })
                   .remove();

nodeExit.select("rect")
        .attr("width", rectW)
        .attr("height", rectH)
        .attr("stroke", "black")
        .attr("stroke-width", 1);

nodeExit.select("text");

// Update the links…
var link = svg.selectAll("path.link")
              .data(links, function (d) {
                return d.target.id;
              })
              .attr("class", function(d) {
            return d.warning === "true" ? "link warning" : "link"});

// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
    .attr("class", function(d) {
            return d.warning === "true" ? "link warning" : "link"
        })
    .attr("x", rectW / 2)
    .attr("y", rectH / 2)
    .attr("d", function (d) {
        var o = {
            x: source.x0.id,
            y: (height-source.y0)
        };
        return diagonal({
            source: o,
            target: o
        });
    });

// Transition links to their new position.
link.transition()
    .duration(duration)
    .attr("class", function(d) {
            return d.warning === "true" ? "link warning" : "link"
        })
    .attr("d", diagonal);

// Transition exiting nodes to the parent's new position.
link.exit().transition()
    .duration(duration)
    .attr("d", function (d) {
        var o = {
            x: source.x.id,
            y: (height-source.y)
        };
        return diagonal({
            source: o,
            target: o
        });
    })
    .attr("class", function(d) {
            return d.warning === "true" ? "link warning" : "link"
        })
    .remove();

// Stash the old positions for transition.
nodes.forEach(function (d) {
    d.x0 = d.y;
    d.y0 = d.x;
});
//}
}

// Toggle children on click.
function click(d) 
{
if (d.children) 
{
    d._children = d.children;
    d.children = null;
} 
else 
{
    d.children = d._children;
    d._children = null;
}

update(d);

document.getElementById('gid').innerHTML = d.gid;
document.getElementById('gname').innerHTML = d.name;
document.getElementById('gmethod').innerHTML = d.method;
document.getElementById('gmtype').innerHTML = d.methodtype;
document.getElementById('gdate').innerHTML = d.date;
document.getElementById('gcountry').innerHTML = d.country;
document.getElementById('gloc').innerHTML = d.location;
document.getElementById('gcname').innerHTML = d.cname;
document.getElementById('gref').innerHTML = d.ref;
document.getElementById('gpid1').innerHTML = d.gpid1;
document.getElementById('gpid2').innerHTML = d.gpid2;
}

function zoom() 
{
var scale = d3.event.scale,
    translation = d3.event.translate,
    tbound = -h * scale,
    bbound = h * scale,
    lbound = (-w + m[1]) * scale,
    rbound = (w - m[3]) * scale;

// limit translation to thresholds
translation = [
    Math.max(Math.min(translation[0], rbound), lbound),
    Math.max(Math.min(translation[1], bbound), tbound)
];

d3.select(".drawarea")
  .attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")");
}
var margin={top:100,right:50,bottom:200,left:1360},
customNodes=新数组(),
图层\u加宽\u标签=新阵列(),
标签w=70,
支管w=70,
m=[100500100500],
realWidth=window.innerWidth,
realHeight=window.innerHeight,
h=实际高度,//-m[0]-m[2],
w=实宽,//-m[0]-m[0],
宽度=3700-margin.right-margin.left,
高度=2050-margin.top-margin.bottom;
根=(函数(){
var=null;
$.ajax({
“异步”:false,
“全局”:错误,
“url”:“/pedigreemimport/json/tree6.json”,
“数据类型”:“json”,
“成功”:函数(数据){
json=数据;
}
});
返回json;
})(); 
var i=0,
持续时间=550,
rectW=80,
rectH=17,
太太
var tree=d3.layout.tree().nodeSize([120,50]);
var diagonal=d3.svg.diagonal()
.投影(功能(d){
返回[d.x+rectW/2,(高度-d.y)+rectH/2];
});
var svg=d3.选择(#graphDiv”).追加(“svg”)
.attr(“宽度”,宽度+边距。右侧+边距。左侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“类”、“绘图区”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
var ms=document.getElementById('maxStep')。值;
var tmpNodes=d3.layout.tree().size([450300])节点(根);
root.x0=函数(d){返回d.x;}//0;
root.y0=函数(d){返回高度-d.y;}//身高1/2;
root.depth=parseInt(root.layer);
customNodes.push(根节点);
制备醇(根、子);
updateNodesXOffset()
//根。子。forEach(塌陷);
更新(根);
d3.选择(“#graphDiv”).样式(“高度”、“660px”);
功能崩溃(d)
{
如果(d.儿童)
{
d、 _children=d.children;
d、 _儿童。forEach(崩溃);
d、 children=null;
}
}
/*d3.选择(“svg”)
.call(d3.behavior.zoom()
.scaleExtent([0.5,5])
。打开(“缩放”,缩放))*/
函数updateNodesXOffset(){
var x_offset=新数组();
x_偏移量[0]=0;
customNodes.forEach(函数(节点){
节点x=0;
如果(node.layer>0){
node.x=x_偏移量[node.layer-1]+层宽\u标签[node.layer-1]+分支\u w;
x_偏移量[node.layer]=node.x;
}
});
}
函数prepareNodes(节点){
forEach(函数(节点){
//警惕(“尝试”);
准备节点;
if(节点子节点){
prepareNodes(node.children);
}
});
}
函数prepareNode(节点){
node.y=getNodeY(node.id);
//。开启(“点击”,点击);
//用于计算标签区域宽度的伪元素。
var fakeTxtBox=svg.append(“svg:text”)
.attr(“id”、“fakeTXT”)
.attr(“文本锚定”,“右”)
.text(node.name+:“+node.gid)
//。在(“单击”,单击(节点));
var this_label_w=fakeTxtBox.node().getComputedTextLength();
svg.select(“#fakeTXT”).remove();
if(层\u加宽\u标签[node.layer]==null){
层\u加宽\u标签[节点.层]=此\u标签\u w;
}否则{
if(此\u标签\u w>层\u更宽\u标签[node.layer]){
层\u加宽\u标签[节点.层]=此\u标签\u w;
}
}
//node.x=nodex;
//将设置x
node.depth=parseInt(node.layer);
customNodes.push(节点);
//在(“单击”,单击(节点));
}
函数getNodeY(id){
var-ret=0;
tmpNodes.some(函数(节点){
如果(node.id==id){
//return x:d3.tree默认为垂直布局。
//ret=node.x
ret=node.x;
回来
}
})
返回ret;
}
函数更新(源)
{
//计算新的树布局。
var nodes=tree.nodes(root).reverse(),
链接=树。链接(节点,函数(d){
返回d.id | |(d.id=++i)
});
//为固定深度进行规格化。
nodes.forEach(函数(d){
d、 y=d.深度*100;
});
//更新节点…
var node=svg.selectAll(“g.node”)
.数据(节点、功能(d){
返回d.id | |(d.id=++i);
});

//如果(node.depth我认为最好的选择是使用Dagre()和cytoscape的组合查看不同的库

有一个名为Dagre-D3的库,您可以将其用作此库的渲染器,因此它看起来像您想要的D3解决方案

查看此提琴,了解Dagre和Cytoscape的基本实现:

var cy = cytoscape({
  container: document.getElementById('cy'),
  elements: {
          nodes: [
            { data: { id: '1' } },
            { data: { id: '2' } },
            { data: { id: '3' } },
            { data: { id: '4' } },
            { data: { id: '5' } },
            { data: { id: '6' } },
            { data: { id: '7' } },
            { data: { id: '8' } },
            { data: { id: '9' } },
            { data: { id: '10' } },
            { data: { id: '11' } },
            { data: { id: '12' } },
            { data: { id: '13' } },
            { data: { id: '14' } },
            { data: { id: '15' } },
            { data: { id: '16' } },
            { data: { id: '17' } },
            { data: { id: '18' } }
          ],
          edges: [
            { data: { source: '1', target: '2' } },
            { data: { source: '1', target: '3' } },
            { data: { source: '2', target: '4' } },
            { data: { source: '4', target: '5' } },
            { data: { source: '4', target: '6' } },
            { data: { source: '5', target: '6' } },
            { data: { source: '5', target: '7' } },
            { data: { source: '7', target: '8' } },
            { data: { source: '3', target: '9' } },
            { data: { source: '3', target: '10' } },
            { data: { source: '10', target: '11' } },
            { data: { source: '11', target: '12' } },
            { data: { source: '12', target: '13' } },
            { data: { source: '12', target: '14' } },
            { data: { source: '14', target: '15' } },
            { data: { source: '15', target: '16' } },
            { data: { source: '16', target: '17' } },
            { data: { source: '16', target: '18' } }

          ]
        },
  layout: {
    name: "dagre",
    rankDir: 'TB' //love this. you can quickly change the orientation here from LR(left to right) TB (top to bottom), RL, BT. Great dropdown option for users here. 
  },
  style: [{
    selector: 'node',
    style: {
      'label': 'data(id)',
      'width': '30%',
      'font-size': '20px',
      'text-valign': 'center',
      'shape': 'circle',
      'background-color': 'rgba(113,158,252,1)', 
      'border': '2px grey #ccc'
    }
  }, {
    selector: 'edge',
    style: {
      'width': 2,
      'line-color': '#ccc',
      'target-arrow-color': '#ccc',
      'target-arrow-shape': 'triangle'
    }
  }]
});