2016-07-11 13 views
5

यदि आप नीचे ढहने वाले पेड़ के साथ खेलते हैं तो आप देखेंगे कि जब आप पेड़ के अंत तक पहुंचते हैं, और नोड्स का विस्तार और पतन करते हैं तो रेखाएं कुछ निराशाजनक चीजें कर रही हैं और मुझे पूरी तरह से यकीन नहीं है कि व्यवहार क्या करता है या enter link description here की मेरी पुनर्लेखन पूरी तरह से आधार से बाहर है। मैं एक फ्लैट डेटा संरचना से बाहर चला गया और इसे एक वृक्ष लेआउट में बदलने के लिए stratify इस्तेमाल किया। अब तक एकमात्र मुद्दा लाइन संक्रमण है ... कोई विचार?d3.js v4 ढीला लिंक संक्रमण संकुचित पेड़ उदाहरण

var data = [{ 
 
    "name": "Hazer 5000", 
 
    "parent": "CFO", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/stephen.jpg" 
 
    }, { 
 
    "name": "Employee 1", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/cory.jpg" 
 
    }, { 
 
    "name": "Analytics Area", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/matt.jpg" 
 
    }, { 
 
    "name": "Employee 2", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/XinheZhang.jpg" 
 
    }, { 
 
    "name": "Employee 3", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/craig.jpg" 
 
    }, { 
 
    "name": "Employee 4", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/youri.jpg" 
 
    }, { 
 
    "name": "Intern 1", 
 
    "parent": "Analytics Area", 
 
    "img": "" 
 
    }, { 
 
    "name": "Inter 2", 
 
    "parent": "Analytics Area", 
 
    "img": "" 
 
    }, { 
 
    "name": "CFO", 
 
    "parent": null, 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Brett.jpg" 
 
    }, { 
 
    "name": "CPA", 
 
    "parent": "CFO", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Wes.jpg" 
 
    }, { 
 
    "name": "Matt's wife", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Amy_R.jpg" 
 
    }, { 
 
    "name": "Employee 5", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/DavidBriley.jpg" 
 
    }, { 
 
    "name": "Employee 6", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/BrittanyAllred_.jpg" 
 
    }, { 
 
    "name": "Employee 7", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Shea.jpg" 
 
    }, { 
 
    "name": "Employee 8", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Mindy.jpg" 
 
    }, { 
 
    "name": "Employee 9", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Jessica_Stacy.jpg" 
 
    }, { 
 
    "name": "Employee 10", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/FraleaneHudson.jpg" 
 
    },{ 
 
    "name": "Employee 11", 
 
    "parent": "Employee 9", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/MeganPierce_.jpg" 
 
    },{ 
 
    "name": "Intern 3", 
 
    "parent": "Employee 8", 
 
    "img": "" 
 
    }, { 
 
    "name": "Intern 4", 
 
    "parent": "Employee 8", 
 
    "img": "" 
 
    } 
 

 
]; 
 

 
var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
 
    width = 960 - margin.right - margin.left, 
 
    height = 800 - margin.top - margin.bottom; 
 

 
var i = 0, 
 
    duration = 750, 
 
    root; 
 

 
var tree = d3.tree() 
 
    .size([height, width]); 
 

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

 

 
var stratify = d3.stratify() 
 
    .id(function(d) { 
 
    return d.name;//This position 
 
    }) 
 
    .parentId(function(d) { 
 
    return d.parent; //What position this position reports to 
 
    }); 
 

 
var root = stratify(data); 
 

 
root.each(function(d) { 
 
    
 
    d.name = d.id; //transferring name to a name variable 
 
    d.id = i; //Assigning numerical Ids 
 
    i++; 
 
    
 
    }); 
 

 
    root.x0 = height/2; 
 
    root.y0 = 0; 
 

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

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

 

 
d3.select(self.frameElement).style("height", "800px"); 
 

 
function update(source) { 
 

 
    // Compute the new tree layout. 
 
    var nodes = tree(root).descendants(), 
 
     links = nodes.slice(1); 
 

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

 
    // Update the nodes… 
 
    var node = svg.selectAll("g.node") 
 
     .data(nodes, function(d) { return d.id || (d.id = ++i); }); 
 

 
    // 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.y0 + "," + source.x0 + ")"; }) 
 
     .on("click", click); 
 

 
    nodeEnter.append("circle") 
 
     .attr("r", 1e-6) 
 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 
 

 
    nodeEnter.append("text") 
 
     .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) 
 
     .attr("dy", ".35em") 
 
     .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) 
 
     .text(function(d) { return d.name; }) 
 
     .style("fill-opacity", 1e-6); 
 

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

 
    nodeUpdate.select("circle") 
 
     .attr("r", 4.5) 
 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#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.y + "," + source.x + ")"; }) 
 
     .remove(); 
 

 
    nodeExit.select("circle") 
 
     .attr("r", 1e-6); 
 

 
    nodeExit.select("text") 
 
     .style("fill-opacity", 1e-6); 
 

 

 
    // Update the links… 
 
    var link = svg.selectAll("path.link") 
 
     .data(links); 
 
    
 
    // Transition links to their new position. 
 
    link.transition() 
 
     .duration(duration) 
 
     .attr("d", connector); 
 

 
    // Enter any new links at the parent's previous position. 
 
    var linkEnter = link.enter().insert("path", "g") 
 
         .attr("class", "link") 
 
         .attr("d", function(d) { 
 
     var o = {x: source.x0, y: source.y0, parent:{x: source.x0, y: source.y0}}; 
 
     return connector(o); 
 
     }); 
 

 
    // Transition links to their new position. 
 
    link.merge(linkEnter).transition() 
 
     .duration(duration) 
 
     .attr("d", connector); 
 

 
    // Transition exiting nodes to the parent's new position. 
 
    link.exit().transition() 
 
     .duration(duration) 
 
     .attr("d", function(d) { 
 
     var o = {x: source.x, y: source.y, parent:{x: source.x, y: source.y}}; 
 
     return connector(o); 
 
     }) 
 
     .remove(); 
 

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

 
// 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); 
 
} 
 

 
function connector(d) { 
 
    return "M" + d.y + "," + d.x + 
 
    "C" + (d.y + d.parent.y)/2 + "," + d.x + 
 
    " " + (d.y + d.parent.y)/2 + "," + d.parent.x + 
 
    " " + d.parent.y + "," + d.parent.x; 
 
}
.node { 
 
    cursor: pointer; 
 
} 
 

 
.node circle { 
 
    fill: #fff; 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
} 
 

 
.node text { 
 
    font: 10px sans-serif; 
 
} 
 

 
.link { 
 
    fill: none; 
 
    stroke: #ccc; 
 
    stroke-width: 1.5px;
<script src="https://d3js.org/d3.v4.min.js"></script>

उत्तर

6

लिंक का डेटा बाइंडिंग के लिए इस्तेमाल किया कुंजी के साथ एक मुद्दा ऐसा लगता है। मैं इस तथ्य का जिक्र कर रहा हूं कि अगर आप दूसरे तर्क के बिना .data(links) पर कॉल करते हैं, तो डी 3 i का उपयोग करता है जब यह एंटर/अपडेट/एक्जिट सेट की गणना करता है, और इसलिए जब आप एक ही लिंक का विस्तार/पतन करते हैं तो अलग-अलग i मान हो सकते हैं।

मेरा मानना ​​है कि मैं यह काम कर रहा है, और सभी मैंने किया था एक समारोह है कि अपनी मूल नोड की आईडी के साथ नोड की आईडी के संयोजन के द्वारा एक अनूठा लिंक आईडी निर्माण करती है के रूप में है कि 2 परम जोड़ने था।

आईई। इस

var link = svg.selectAll("path.link") 
    .data(links) 

के बजाय मैंने यह इस

var link = svg.selectAll("path.link") 
    .data(links, function(link) { var id = link.id + '->' + link.parent.id; return id; }); 

इसे आजमाएं:

var data = [{ 
 
    "name": "Hazer 5000", 
 
    "parent": "CFO", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/stephen.jpg" 
 
    }, { 
 
    "name": "Employee 1", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/cory.jpg" 
 
    }, { 
 
    "name": "Analytics Area", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/matt.jpg" 
 
    }, { 
 
    "name": "Employee 2", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/XinheZhang.jpg" 
 
    }, { 
 
    "name": "Employee 3", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/craig.jpg" 
 
    }, { 
 
    "name": "Employee 4", 
 
    "parent": "Hazer 5000", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/youri.jpg" 
 
    }, { 
 
    "name": "Intern 1", 
 
    "parent": "Analytics Area", 
 
    "img": "" 
 
    }, { 
 
    "name": "Inter 2", 
 
    "parent": "Analytics Area", 
 
    "img": "" 
 
    }, { 
 
    "name": "CFO", 
 
    "parent": null, 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Brett.jpg" 
 
    }, { 
 
    "name": "CPA", 
 
    "parent": "CFO", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Wes.jpg" 
 
    }, { 
 
    "name": "Matt's wife", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Amy_R.jpg" 
 
    }, { 
 
    "name": "Employee 5", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/DavidBriley.jpg" 
 
    }, { 
 
    "name": "Employee 6", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/BrittanyAllred_.jpg" 
 
    }, { 
 
    "name": "Employee 7", 
 
    "parent": "CPA", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Shea.jpg" 
 
    }, { 
 
    "name": "Employee 8", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Mindy.jpg" 
 
    }, { 
 
    "name": "Employee 9", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/Jessica_Stacy.jpg" 
 
    }, { 
 
    "name": "Employee 10", 
 
    "parent": "Matt's wife", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/FraleaneHudson.jpg" 
 
    },{ 
 
    "name": "Employee 11", 
 
    "parent": "Employee 9", 
 
    "img": "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-342/MeganPierce_.jpg" 
 
    },{ 
 
    "name": "Intern 3", 
 
    "parent": "Employee 8", 
 
    "img": "" 
 
    }, { 
 
    "name": "Intern 4", 
 
    "parent": "Employee 8", 
 
    "img": "" 
 
    } 
 

 
]; 
 

 
var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
 
    width = 960 - margin.right - margin.left, 
 
    height = 800 - margin.top - margin.bottom; 
 

 
var i = 0, 
 
    duration = 750, 
 
    root; 
 

 
var tree = d3.tree() 
 
    .size([height, width]); 
 

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

 

 
var stratify = d3.stratify() 
 
    .id(function(d) { 
 
    return d.name;//This position 
 
    }) 
 
    .parentId(function(d) { 
 
    return d.parent; //What position this position reports to 
 
    }); 
 

 
var root = stratify(data); 
 

 
root.each(function(d) { 
 
    
 
    d.name = d.id; //transferring name to a name variable 
 
    d.id = i; //Assigning numerical Ids 
 
    i++; 
 
    
 
    }); 
 

 
    root.x0 = height/2; 
 
    root.y0 = 0; 
 

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

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

 

 
d3.select(self.frameElement).style("height", "800px"); 
 

 
function update(source) { 
 

 
    // Compute the new tree layout. 
 
    var nodes = tree(root).descendants(), 
 
     links = nodes.slice(1); 
 

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

 
    // Update the nodes… 
 
    var node = svg.selectAll("g.node") 
 
     .data(nodes, function(d) { return d.id || (d.id = ++i); }); 
 

 
    // 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.y0 + "," + source.x0 + ")"; }) 
 
     .on("click", click); 
 

 
    nodeEnter.append("circle") 
 
     .attr("r", 1e-6) 
 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 
 

 
    nodeEnter.append("text") 
 
     .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) 
 
     .attr("dy", ".35em") 
 
     .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) 
 
     .text(function(d) { return d.name; }) 
 
     .style("fill-opacity", 1e-6); 
 

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

 
    nodeUpdate.select("circle") 
 
     .attr("r", 4.5) 
 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#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.y + "," + source.x + ")"; }) 
 
     .remove(); 
 

 
    nodeExit.select("circle") 
 
     .attr("r", 1e-6); 
 

 
    nodeExit.select("text") 
 
     .style("fill-opacity", 1e-6); 
 

 

 
    // Update the links… 
 
    var link = svg.selectAll("path.link") 
 
     .data(links, function(link) { var id = link.id + '->' + link.parent.id; return id; }); 
 
    
 
    // Transition links to their new position. 
 
    link.transition() 
 
     .duration(duration) 
 
     .attr("d", connector); 
 

 
    // Enter any new links at the parent's previous position. 
 
    var linkEnter = link.enter().insert("path", "g") 
 
         .attr("class", "link") 
 
         .attr("d", function(d) { 
 
     var o = {x: source.x0, y: source.y0, parent:{x: source.x0, y: source.y0}}; 
 
     return connector(o); 
 
     }); 
 

 
    // Transition links to their new position. 
 
    link.merge(linkEnter).transition() 
 
     .duration(duration) 
 
     .attr("d", connector); 
 

 
    // Transition exiting nodes to the parent's new position. 
 
    link.exit().transition() 
 
     .duration(duration) 
 
     .attr("d", function(d) { 
 
     var o = {x: source.x, y: source.y, parent:{x: source.x, y: source.y}}; 
 
     return connector(o); 
 
     }) 
 
     .remove(); 
 

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

 
// 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); 
 
} 
 

 
function connector(d) { 
 
    return "M" + d.y + "," + d.x + 
 
    "C" + (d.y + d.parent.y)/2 + "," + d.x + 
 
    " " + (d.y + d.parent.y)/2 + "," + d.parent.x + 
 
    " " + d.parent.y + "," + d.parent.x; 
 
}
.node { 
 
    cursor: pointer; 
 
} 
 

 
.node circle { 
 
    fill: #fff; 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
} 
 

 
.node text { 
 
    font: 10px sans-serif; 
 
} 
 

 
.link { 
 
    fill: none; 
 
    stroke: #ccc; 
 
    stroke-width: 1.5px;
<script src="https://d3js.org/d3.v4.min.js"></script>

+0

'वर लिंक = svg.selectAll (" path.link ") .डेटा (लिंक, फ़ंक्शन (डी) {वापसी डी.आईडी;}); 'इसे काम करने के लिए भी पर्याप्त था। सही दिशा में मुझे इंगित करने के लिए धन्यवाद !! – Tekill

+1

@ योरिनियम ओह हाँ - 'डी.आईडी' काम करता है क्योंकि प्रति बच्चे हमेशा एक लिंक/माता-पिता रहता है। – meetamit

+0

आपकी मदद @meetamit के लिए धन्यवाद – Tekill