在d3 js双树中单独翻转链接 [英] Flipping the links alone in a d3 js doubletree
本文介绍了在d3 js双树中单独翻转链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我按照本教程制作双树并将弯头连接器转换为对角线连接器。
这是我尝试的
到目前为止,应该向左边的边也向正确的方向,我怎么能翻转那些边缘到左边。
我试着替换 nodes.forEach
函数,如下所示。在第二种情况下,链接被翻转,但节点从右到左。
nodes.forEach {
if(d.isRight)
{
dy = d.depth * 180 + halfWidth;
}
else
{
dy = width - (d.depth * 180 + halfWidth);
}
});
无法使用。任何帮助是赞赏。
var margin = {top:30,right:10,bottom:10,left:10},width = 960 - margin.left - margin.right,halfWidth = width / 2,height = 500 - margin.top - margin.bottom,i = 0,duration = 500,root; var getChildren = function(d){var a = ; if(d.winners)for(var i = 0; i
.node circle {cursor:pointer; fill:#fff;中风:钢蓝stroke-width:1.5px;}。node text {font:10px sans-serif;} path.link {fill:none; stroke:#ccc; stroke-width:1.5px;}
< script src =https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js>< / script>< div id =chart>< / div>
解决方案
var margin = {top:30,right:10,bottom:10,left:10},width = 960 - margin.left - margin.right,halfWidth = width / 2,height = 500 - margin.top - margin.bottom ,i = 0,duration = 500,root; var getChildren = function(d){var a = []; if(d.winners)for(var i = 0; i
.node circle {cursor:pointer; fill:#fff;中风:钢蓝stroke-width:1.5px;}。node text {font:10px sans-serif;} path.link {fill:none; stroke:#ccc; stroke-width:1.5px;}
< script src =https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js>< / script>< div id =chart>< / div>
I'm following this tutorial to make a double tree and convert the elbow connectors into diagonal connectors. Here is what I tried
As of now the edges that are supposed to go to the left are also going in the right direction , how can i flip those edges to the left.
I tried replacing the nodes.forEach
function as follows. In the second case the links got flipped , but the nodes went from right to left.
nodes.forEach(function(d) {
if(d.isRight)
{
d.y = d.depth * 180 + halfWidth;
}
else
{
d.y = width - (d.depth * 180 + halfWidth);
}
});
Did not work. Any help is appreciated.
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 10
},
width = 960 - margin.left - margin.right,
halfWidth = width / 2,
height = 500 - margin.top - margin.bottom,
i = 0,
duration = 500,
root;
var getChildren = function(d) {
var a = [];
if (d.winners)
for (var i = 0; i < d.winners.length; i++) {
d.winners[i].isRight = false;
d.winners[i].parent = d;
a.push(d.winners[i]);
}
if (d.challengers)
for (var i = 0; i < d.challengers.length; i++) {
d.challengers[i].isRight = true;
d.challengers[i].parent = d;
a.push(d.challengers[i]);
}
return a.length ? a : null;
};
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var connector = diagonal;
var calcLeft = function(d) {
var l = d.y;
if (!d.isRight) {
l = d.y - halfWidth;
l = halfWidth - l;
}
return {
x: d.x,
y: l
};
};
var vis = d3.select("#chart").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 + ")");
setTimeout(function() {
var json = {
"name": "Overall Winner",
"winners": [{
"name": "Winner Left 1",
"winners": [{
"name": "Winner Left 3"
}, {
"name": "Winner Left 4"
}]
}, {
"name": "Winner Left 2"
}],
"challengers": [{
"name": "Challenger Right 1",
"challengers": [{
"name": "Challenger Right 3"
}, {
"name": "Challenger Right 4"
}]
}, {
"name": "Challenger Right 2",
"challengers": [{
"name": "Challenger Right 5"
}, {
"name": "Challenger Right 6"
}]
}]
};
root = json;
root.x0 = height / 2;
root.y0 = width / 2;
var t1 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
return d.winners;
}),
t2 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
return d.challengers;
});
t1.nodes(root);
t2.nodes(root);
var rebuildChildren = function(node) {
node.children = getChildren(node);
if (node.children) node.children.forEach(rebuildChildren);
}
rebuildChildren(root);
root.isRight = false;
update(root);
});
var toArray = function(item, arr, d) {
arr = arr || [];
var dr = d || 1;
var i = 0,
l = item.children ? item.children.length : 0;
arr.push(item);
if (item.position && item.position === 'left') {
dr = -1;
}
item.y = dr * item.y;
for (; i < l; i++) {
toArray(item.children[i], arr, dr);
}
return arr;
};
function update(source) {
// Compute the new tree layout.
var nodes = toArray(source);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180 + halfWidth;
});
// Update the nodes…
var node = vis.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("dy", function(d) {
return d.isRight ? 14 : -8;
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
p = calcLeft(d);
return "translate(" + p.y + "," + p.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) {
p = calcLeft(d.parent || source);
return "translate(" + p.y + "," + p.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links...
var link = vis.selectAll("path.link")
.data(tree.links(nodes), 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 connector({
source: o,
target: o
});
});
// Transition links to their new position.
link.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 = calcLeft(d.source || source);
if (d.source.isRight) o.y -= halfWidth - (d.target.y - d.source.y);
else o.y += halfWidth - (d.target.y - d.source.y);
return connector({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
var p = calcLeft(d);
d.x0 = p.x;
d.y0 = p.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(source);
}
}
.node circle {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>
解决方案
With some efforts found a work around to do the same.
Here goes the code.
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 10
},
width = 960 - margin.left - margin.right,
halfWidth = width / 2,
height = 500 - margin.top - margin.bottom,
i = 0,
duration = 500,
root;
var getChildren = function(d) {
var a = [];
if (d.winners)
for (var i = 0; i < d.winners.length; i++) {
d.winners[i].isRight = false;
d.winners[i].parent = d;
a.push(d.winners[i]);
}
if (d.challengers)
for (var i = 0; i < d.challengers.length; i++) {
d.challengers[i].isRight = true;
d.challengers[i].parent = d;
a.push(d.challengers[i]);
}
return a.length ? a : null;
};
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var connector = diagonal;
var calcLeft = function(d) {
var l = d.y;
if (!d.isRight) {
l = d.y - halfWidth;
l = halfWidth - l;
}
return {
x: d.x,
y: l
};
};
var vis = d3.select("#chart").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 + ")");
setTimeout(function() {
var json = {
"name": "Overall Winner",
"winners": [{
"name": "Winner Left 1",
"winners": [{
"name": "Winner Left 3"
}, {
"name": "Winner Left 4"
}]
}, {
"name": "Winner Left 2"
}],
"challengers": [{
"name": "Challenger Right 1",
"challengers": [{
"name": "Challenger Right 3"
}, {
"name": "Challenger Right 4"
}]
}, {
"name": "Challenger Right 2",
"challengers": [{
"name": "Challenger Right 5"
}, {
"name": "Challenger Right 6"
}]
}]
};
root = json;
root.x0 = height / 2;
root.y0 = width / 2;
var t1 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
return d.winners;
}),
t2 = d3.layout.tree().size([height, halfWidth]).children(function(d) {
return d.challengers;
});
t1.nodes(root);
t2.nodes(root);
var rebuildChildren = function(node) {
node.children = getChildren(node);
if (node.children) node.children.forEach(rebuildChildren);
}
rebuildChildren(root);
root.isRight = false;
update(root);
});
var toArray = function(item, arr, d) {
arr = arr || [];
var dr = d || 1;
var i = 0,
l = item.children ? item.children.length : 0;
arr.push(item);
if (item.position && item.position === 'left') {
dr = -1;
}
item.y = dr * item.y;
for (; i < l; i++) {
toArray(item.children[i], arr, dr);
}
return arr;
};
function update(source) {
// Compute the new tree layout.
var nodes = toArray(source);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
if (d.isRight) {
d.y = d.depth * 180 + halfWidth;
} else {
d.y = width - (d.depth * 180 + halfWidth);
}
});
// Update the nodes…
var node = vis.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("dy", function(d) {
return d.isRight ? 14 : -8;
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
console.log(d);
p = calcLeft(d);
if (d.isRight) {
return "translate(" + p.y + "," + p.x + ")";
} else {
if (p.y != 470) {
var temp = p.y - 470;
p.y = 470 - temp;
return "translate(" + p.y + "," + p.x + ")";
} else {
return "translate(" + p.y + "," + p.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) {
p = calcLeft(d.parent || source);
return "translate(" + p.y + "," + p.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links...
var link = vis.selectAll("path.link")
.data(tree.links(nodes), 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 connector({
source: o,
target: o
});
});
// Transition links to their new position.
link.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 = calcLeft(d.source || source);
if (d.source.isRight) o.y -= halfWidth - (d.target.y - d.source.y);
else o.y += halfWidth - (d.target.y - d.source.y);
return connector({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
var p = calcLeft(d);
d.x0 = p.x;
d.y0 = p.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(source);
}
}
.node circle {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>
这篇关于在d3 js双树中单独翻转链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文