我是 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 + ")");
}
我认为您最好的选择是查看不同的库,使用Dagre的组合(https://github.com/dagrejs/dagre)和细胞景观
有一个名为Dagre-D3的库,您可以将其用作该库的渲染器,因此它看起来像您想要的D3解决方案。
看看这个小提琴,看看Dagre和Cytoscape的基本实现:https://jsfiddle.net/KateJean/xweudjvm/
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'
}
}]
});
如果我没弄错的话,树通常是一个列表,其中的元素按特定顺序排列。孩子们不在他们自己的子列表中,他们都在同一个列表中。 所以,我试图创建一个Tree类,其中包含TreeNodes(类)使用Tree类中的List。 我如何跟踪父母/孩子/叶子?如果父母“父母1”,有两个孩子“孩子A”和“孩子B”,我如何将他们联系在一起?
我已经实现了一个TreeModel来调整存量数据模型,以便将其可视化为JTree。我遇到了一个问题,节点有多个相同的子(叶)节点。例如,考虑一个JTree,它的叶节点是Strings。每当父节点包含具有相同String值的子节点时,就会出现问题。这些叶节点的TreePath是相同的,作为Strings,equals()返回true。留档明确地调用这个: JTree及其相关类广泛使用TreePath
我一直在将代码从JIT转换到D3,并使用树布局。我已从中复制了代码http://mbostock.github.com/d3/talk/20111018/tree.html使用我的树数据,但我想做更多。 在我的例子中,我想创建子节点,这些子节点合并回一个较低级别的父节点,我意识到这更像是一个有向图结构,但是希望树能够适应这一点(即注意子节点之间的公共id应该合并)。 因此,基本上,一棵树在从父母到
上面的数组 id=311的父节点是 id=31,id=2的父节点为null; 请问应该怎么解决?
在上面的XML中,父节点和它的一个子节点(即中心)有相同的标记名。我知道我可以在主标记的索引0处进行多个步骤的解析,然后中心标记的索引0将给出ID,中心标记的索引1将给出中心的值333,等等,但是有没有一种方法可以直接得到ID和中心的值(11,333)。
父节点的分数值socre等于直属子节点的score之和,只有最有一级节点的score有值,所以需要倒序求出每个父节点score的值,没想出来要怎么搞,求助大神的帮助 总结就是:3级加起来等于2级,2级加起来等于1级