我正在尝试使用 d3.js 渲染树图(我很新)。所以我不知道如何使从下到上的方向。我在这里参考了这个例子。
我还希望每个节点单击节点属性都会显示(单击函数调用)。
有人可以启发我吗?谢谢
到目前为止,这是我的代码。
var orientation = {
"": {
size: [width, height],
x: function(node) { return node.x; },
y: function(node) { return height - node.y; }
},
};
var data = (function () {
var jason = null;
$.ajax({
'async': false,
'global': false,
'url': "/../GMGR_restructure/json/tree6.json",
'dataType': "json",
'success': function (data) {
jason = data;
}
});
return jason;
})();
var realWidth = window.innerWidth;
var realHeight = window.innerHeight;
var margin = {top: 140, right: 10, bottom: 140, left: 10},
m = [0, 1000, 0, 100],
width = 1500 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom
h = realHeight -m[0] -m[2],
rectW = 200;
rectH = 30;
w = realWidth -m[0] -m[0];
var customNodes = new Array(),
tmpNodes,
label_w = 70,
branch_w = 70,
layer_wider_label = new Array(),
depencencyChart;
function graph2() {
var ms = document.getElementById('maxStep').value;
tmpNodes = d3.layout.tree().size([600, 1000]).nodes(data);//.on("click", click);
//Create a svg canvas
depencencyChart = d3.select("#graphDiv").append("svg:svg")
.data(d3.entries(orientation))
.attr("width", 2000)
.attr("height", 1000)
.append("svg:g")
.attr("class","drawarea")
.attr("transform", "translate(80, 80)") // shift everything to the right
//.on("click", click);
var fakeTxtBox = depencencyChart.append("svg:text")
.attr("id", "fakeTXT")
.attr("text-anchor", "right")
.text(data.name + "(" + data.gid + ")");
//.on("click", click);
layer_wider_label[0] = fakeTxtBox.node().getComputedTextLength();
depencencyChart.select("#fakeTXT").remove();
data.y = getNodeY(data.id);
data.x = 0;
data.depth = parseInt(data.layer);
customNodes.push(data);//.on("click", click);
prepareNodes(data.children);//.on("click", click(data));
//align nodes.
updateNodesXOffset()
if(ms==""||ms==" "||ms=="All")
drawChart2();
else
drawChart(ms);
d3.select("g")
.call(d3.behavior.zoom()
.scaleExtent([0.1,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 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;
return;
}
})
return ret;
}
function prepareNodes(nodes) {
nodes.forEach(function(node) {
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 = depencencyChart.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();
depencencyChart.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;
}
}
//x will be set
node.depth = parseInt(node.layer);
customNodes.push(node);
//node.on("click", click(node));
}
function customSpline(d) {
var p = new Array();
p[0] = d.source.x + "," + d.source.y;
p[3] = d.target.x + "," + d.target.y;
var m = (d.source.x + d.target.x) / 2
p[1] = m + "," + d.source.y;
p[2] = m + "," + d.target.y;
//This is to change the points where the spline is anchored
//from [source.right,target.left] to [source.top,target.bottom]
// var m = (d.source.y + d.target.y)/2
// p[1] = d.source.x + "," + m;
// p[2] = d.target.x + "," + m;
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
}
function drawChart(ms) {
var cnt=0;
customNodes.forEach(function(node) { //alert(node.layer);
if(node.depth <= ms){
cnt++;
var nodeSVG = depencencyChart.append("svg:g")
.attr("transform", "translate(" + node.x + "," + node.y + ")")
//alert(node.depth);
if (node.depth > 0) {
nodeSVG.append("svg:circle")
.attr("stroke", node.children ? "#3191c1" : "#269926")
.attr("fill", "#fff")
.attr("r", 3)
}
var txtBox = nodeSVG.append("svg:text")
.on("click", click)
.attr("class", "name")
.attr("dx", 8)
.attr("dy", 4)
//.attr("fill", node.current ? "#ffffff" : node.children ? "#226586" : "#269926")
.attr("fill", node.current ? "#ffffff" : node.children ? "#ffffff" : "#ffffff")
.text(node.name)
//.text(node.name + " \n (" + node.gid + ") ")
//.attr("dx", 8)
//.attr("dy", 8)
//.text(node.gid)
var txtW = txtBox.node().getComputedTextLength();
nodeSVG.insert("rect", "text")
.attr("fill", node.children ? "#3191c1" : "#3191c1")
.attr("stroke", "black")
.attr("width", txtW + 8)
.attr("height", "20")
.attr("y", "-12")
.attr("x", "5")
.attr("rx", 4)
.attr("ry", 4)
//.on("click", click(node))
if (node.current) {
nodeSVG.insert("rect", "text")
.attr("fill", node.children ? "#FF4D4D" : "#269926")
.attr("width", txtW + 8)
.attr("height", "20")
.attr("y", "-12")
.attr("x", "5")
.attr("rx", 4)
.attr("ry", 4)
}
//if(cnt <= ms){
if (node.children) {
node.x = node.x + txtW + 20;
//prepare links;
var links = new Array();
node.children.forEach(function(child) {
var st = new Object();
st.source = node;
// st.parent = node;
st.target = child;
st.warning = child.warning;
links.push(st);
})
//.on("click", click(node));
//draw links (under nodes)
depencencyChart.selectAll("pathlink")
.data(links)
.enter().insert("svg:path", "g")
.attr("class", function(d) {
return d.warning === "true" ? "link warning" : "link"
})
.attr("d", customSpline)
//draw a node at the end of the link
nodeSVG.append("svg:circle")
.attr("stroke", "#3191c1")
.attr("fill", "#fff")
.attr("r", 5.5)
//.on("click", click(node))
.attr("transform", "translate(" + (txtW + 20) + ",0)");
//}
}
//node.on("click", click(node));
}
});
d3.select("svg")
.call(d3.behavior.zoom()
.scaleExtent([0.5, 10])
.on("zoom", zoom));
//update(data);
}
function drawChart2() {
var cnt=0;
customNodes.forEach(function(node) {
//if(node.depth <= ms){
cnt++;
var nodeSVG = depencencyChart.append("svg:g")
.attr("transform", "translate(" + node.x + "," + node.y + ")")
//alert(node.depth);
if (node.depth > 0) {
nodeSVG.append("svg:circle")
.attr("stroke", node.children ? "#3191c1" : "#269926")
.attr("fill", "#fff")
.attr("r", 3)
//.attr("x",(node.x-5))
//.attr("y",(node.y-8))
}
var txtBox = nodeSVG.append("svg:text")
//.on("click", click(node))
.attr("class", "name")
.attr("dx", 8)
.attr("dy", 4)
//.attr("fill", node.current ? "#ffffff" : node.children ? "#226586" : "#269926")
.attr("fill", node.current ? "#ffffff" : node.children ? "#ffffff" : "#ffffff")
.text(node.name)
/*.html(function(node){
var str=node.name;
if(str.length>10){
var txt1=str.slice(0,10);
txt1+="<br/>";
txt2=str.slice(10,str.length);
return txt1+txt2;
}
return node.name;
});*/
//.text(node.name + " \n (" + node.gid + ") ")
//.attr("dx", 8)
//.attr("dy", 8)
//.text(node.gid)
var txtW = txtBox.node().getComputedTextLength();
nodeSVG.insert("rect", "text")
.attr("fill", node.children ? "#3191c1" : "#3191c1")
.attr("stroke", "black")
.attr("width", txtW + 8)
.attr("height", "20")
.attr("y", "-12")
.attr("x", "5")
.attr("rx", 4)
.attr("ry", 4)
//.on("click", click(node))
if (node.current) {
nodeSVG.insert("rect", "text")
.attr("fill", node.children ? "#FF4D4D" : "#269926")
.attr("width", txtW + 8)
.attr("height", "20")
.attr("y", "-12")
.attr("x", "5")
.attr("rx", 4)
.attr("ry", 4)
}
//if(cnt <= ms){
if (node.children) {
node.x = node.x + txtW + 20;
//prepare links;
var links = new Array();
node.children.forEach(function(child) {
var st = new Object();
st.source = node;
// st.parent = node;
st.target = child;
st.warning = child.warning;
links.push(st);
})
//.on("click", click(node));
//draw links (under nodes)
depencencyChart.selectAll("pathlink")
.data(links)
.enter().insert("svg:path", "g")
.attr("class", function(d) {
return d.warning === "true" ? "link warning" : "link"
})
.attr("d", customSpline)
//draw a node at the end of the link
nodeSVG.append("svg:circle")
.attr("stroke", "#3191c1")
.attr("fill", "#fff")
.attr("r", 5.5)
//.on("click", click(node))
.attr("transform", "translate(" + (txtW + 20) + ",0)");
//}
}
//node.on("click", click(node));
//}
});
d3.select("svg")
.call(d3.behavior.zoom()
.scaleExtent([0.5, 10])
.on("zoom", zoom));
//update(data);
}
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 + ")");
}
// 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 click(node)
{
alert(node.name);
//document.getElementById('gid').innerHTML = "sucess";
document.getElementById('gid').innerHTML = node.gid;
document.getElementById('gname').innerHTML = node.name;
document.getElementById('gmethod').innerHTML = node.method;
document.getElementById('gmtype').innerHTML = node.methodtype;
document.getElementById('gdate').innerHTML = node.date;
document.getElementById('gcountry').innerHTML = node.country;
document.getElementById('gloc').innerHTML = node.location;
document.getElementById('gcname').innerHTML = node.cname;
document.getElementById('gref').innerHTML = node.ref;
document.getElementById('gpid1').innerHTML = node.gpid1;
document.getElementById('gpid2').innerHTML = node.gpid2;
//document.getElementById('try').value = d.name;
}*/