我正在尝试在树布局上找到特定节点。我在plunkr上找到了这个例子:
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(function(d1){d1.parent = d; collapse(d1);});
d.children = null;
}}
function find(d, name) {
if (d.name == name){
while(d.parent){
d = d.parent;
click(d)
}
return;
}
if (d.children) {
d.children.forEach(function(d){find(d, name)});
} else if(d._children){
d._children.forEach(function(d){find(d, name)});
}}
[root].forEach(collapse);
var name = "layout"
find (root, name)
update(root);
http://plnkr.co/edit/Ce5Ub8PWXblSMcrYlkHa?p=preview找到给定名称的特定节点。
我采用它来找到一个给出ID的节点。
我实现了两个问题:
1-代码在控制台中生成错误“错误:属性转换:预期数量”,翻译(undefined,undefi ...“。我认为这是由于x和y坐标变为空,但我无法识别确切的条件。此错误也出现在原始示例中
2-如果我调用一次查找例程(通过单击调用find_name()的查找按钮并注释掉对查找函数的第二次调用),它会工作,但是如果我多次调用它(通过un -commenting并启用第二次调用find),树折叠到根节点。
非常感谢您对理解此行为的任何帮助。
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// ************** Generate the tree diagram *****************
var data =[{"sid":"1","parent":"null","name_ar":"Hashim"},{"sid":"2","parent":"1","name_ar":"wahb"},{"sid":"3","parent":"1","name_ar":"Abdulmuttaleb"},{"sid":"4","parent":"2","name_ar":"Amina"},{"sid":"5","parent":"3","name_ar":"Abutaleb"},{"sid":"6","parent":"3","name_ar":"Abdulla"},{"sid":"7","parent":"3","name_ar":"Abbas"},{"sid":"8","parent":"3","name_ar":"Hamza"},{"sid":"9","parent":"6","name_ar":"Mohammed (Prophet)"},{"sid":"10","parent":"9","name_ar":"Alqassim"},{"sid":"11","parent":"9","name_ar":"Um Kalthoum"},{"sid":"12","parent":"9","name_ar":"Zainab"},{"sid":"13","parent":"9","name_ar":"Ruqaya"},{"sid":"14","parent":"9","name_ar":"Fatima"},{"sid":"15","parent":"9","name_ar":"Ibrahim"},{"sid":"16","parent":"9","name_ar":"Abdulla"},{"sid":"17","parent":"9","name_ar":"Muhsen"},{"sid":"18","parent":"5","name_ar":"Ali"},{"sid":"19","parent":"18","name_ar":"Hassan"},{"sid":"20","parent":"18","name_ar":"Hussain"},{"sid":"21","parent":"20","name_ar":"Ali Zain Alabbideen"},{"sid":"22","parent":"21","name_ar":"Mohammed Baqer"},{"sid":"23","parent":"22","name_ar":"Jafar Sadeq"},{"sid":"24","parent":"23","name_ar":"Mousa Kadim"},{"sid":"25","parent":"24","name_ar":"Ali AlAreed"},{"sid":"26","parent":"24","name_ar":"Ibrahim Murtada"},{"sid":"27","parent":"26","name_ar":"Mousa (the second)"},{"sid":"28","parent":"27","name_ar":"Ahmed"},{"sid":"29","parent":"28","name_ar":"Hussain"},{"sid":"30","parent":"29","name_ar":"Abu Alqassim Mohammed"},{"sid":"31","parent":"30","name_ar":"Najm Aldeen Mahdi"}];
//------------------
//the find function is global
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(function(d1){d1.parent = d; collapse(d1);});
d.children = null;
}
}
function find(d, sid) {
if (d.sid == sid){
while(d.parent){
d = d.parent;
click(d)
}
return;
}
if (d.children) {
d.children.forEach(function(d){find(d, sid)});
} else if(d._children){
d._children.forEach(function(d){find(d, sid)});
}
}
function find_name(){
[root].forEach(collapse); //iterate each node and collapse
find(root,25);
find(root,31);
update(root);
}
//------------------
var margin = {top: 25, right: 120, bottom: 20, left: 120},
width = 10000 - margin.right - margin.left,
height = 5000 - margin.top - margin.bottom;
var i = 0,
duration = 750,
rectW = 100,
rectH = 30,
root;
var enteredId = 7402;
//zoom functionality
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var tree = d3.layout.tree()
.nodeSize([110, 50]);
var diagonal = d3.svg.diagonal()
.projection(function (d) { return [d.x + rectW / 2, d.y + rectH / 2]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.on("wheel.zoom", null) //disable zooming on mouse wheel scroll
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//create a name-based map for the nodes
//which starts with an empty object and iterates over the data array, adding an entry for each node
//for the flat array
var dataMap = data.reduce(function(map, node) {
map[node.sid] = node;
return map;
}, {});
//iteratively add each child to its parents, or to the root array if no parent is found
//for the flat array
var treeData = [];
data.forEach(function(node) {
// add to parent
var parent = dataMap[node.parent];
if (parent) {
// create child array if it doesn't exist
(parent.children || (parent.children = []))
// add node to child array
.push(node);
} else {
// parent is null or missing
treeData.push(node);
}
});
root = treeData[0];
root.x0 = height / 2;
root.y0 = 0;
//------------------------------------------------------
var nodes = tree.nodes(root);
function collapseLevel(d) {
if (d.children && d.depth > 23) {
d._children = d.children;
d._children.forEach(collapseLevel);
d.children = null;
} else if (d.children) {
d.children.forEach(collapseLevel);
}
}
root.children.forEach(collapseLevel);//iterate each node and collapse excluding node zero
//------------------------------------------------------
update(root);
d3.select(self.frameElement).style("height", "500px");
function zoomed() {
svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// 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.
//vertical tree by swaping y0 and x0
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.x0 + "," + source.y0 + ")"; })
.on("click", click)
.on("mouseover", function(d) {
var g = d3.select(this); // The node
// The class is used to remove the additional text later
var info = g.append('text')
.classed('info', true)
.attr('x', 20)
.attr('y', 10)
.text(function(d) { return d.name_ar + " " + d.sid }); // need to put good background for tooltip
})
.on("mouseout", function() {
// Remove the info text on mouse out.
d3.select(this).select('text.info').remove()
});
;
nodeEnter.append("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", function (d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", rectW / 2)
.attr("y", rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name_ar; })
.style("fill-opacity", 1);
//vertical
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
nodeUpdate.select("rect")
.attr("width", rectW)
.attr("height", rectH)
.attr("stroke", "black")
.attr("stroke-width", 1)
.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.
//vertical
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.x + "," + 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; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.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, y: source.y};
return diagonal({source: o, target: 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);
}
//-------------------------------------
</script>
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 14px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tree Example</title>
<header>
<button onclick="find_name()">find</button>
</header>
</head>
答案 0 :(得分:0)
第一个问题中错误的原因“代码在控制台中生成错误”错误:属性转换:预期数字,“translate(undefined,undefi”是由于SID是字符。我将其转换为整数并且不会产生错误。