【发布时间】:2013-11-15 16:32:18
【问题描述】:
我正在尝试实现我在 D3 网站上看到的展开/折叠功能,但我得到的是,当我运行此功能时,某些节点会具有多个标签。
var width = 960,
height = 500;
var node,
path,
root, nodes, links, link;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force();
var resource = $.getJSON('js/nodes.json', function(data)
{
root = restructure(data);
render();
})
function restructure(data)
{
var root = data[0];
data.splice(0,1);
root.children = data;
_.each(root.children, function(child)
{
child._children = child.links;
})
return root;
}
function flatten(root) {
// return root;
var nodes = [];
var links = [];
function rec(node) {
var sourceNode = addNode(nodes, node);
if (node.children)
{
//sourceNode.children = [];
node.children.forEach(function(child)
{
var targetNode = rec(child);
links.push({source:sourceNode, target:targetNode});
//sourceNode.children.push(targetNode);
})
}
return sourceNode;
}
rec(root);
return {nodes:d3.values(nodes), links:links};
}
function addNode(collection, node) {
if(collection[node.name] != null)
return collection[node.name];
collection[node.name] = node;
return node;
}
function render()
{
var flat = flatten(root);
var nodes = flat.nodes;
var links = flat.links;
nodes = tree.nodes(elements.nodes).reverse();
links = tree.links(nodes);*/
force.nodes(nodes)
.links(links)
.size([width, height])
.linkDistance(160)
.charge(-1500)
.on("tick", tick)
.start();
var drag = force.drag()
.on("dragstart", dragstart);
function dragstart(d) {
d.fixed = true;
d3.select(this).classed("fixed", true);
}
function isRoot(node)
{
return node.id == root.id
}
/* link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link");*/
// Update the links…
link = svg.selectAll("line.link")
.data(force.links(), function(d) { return d.target.id; });
// Enter any new links.
link.enter().insert("line", ".node")
.attr("class","link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; })
.style("stroke-width",function(l)
{
console.log(l.source.rank + ':' + l.target.rank);
var val = Math.min(10,Math.max(1,Math.log(Math.max(Math.abs(l.source.rank),Math.abs(l.target.rank)))));
console.log('width: ' + val);
return val;
});
// Exit any old links.
link.exit().remove();
node = svg.selectAll(".node")
.data(force.nodes());
node.exit().remove();
node.enter().append("g")
.attr("class", "node")
.attr("id", function(d) { return d.id; })
.on("click", click)
.on("dblclick", doubleclick)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.call(force.drag);
node.append("image")
.attr("xlink:href", function (d)
{
return "../img/icon-location.png";
})
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
/* node.append("circle")
.attr("r", function(d)
{
return isRoot(d)? 14:8;
})
.style("fill",function(d)
{
return isRoot(d)? "steelblue":"";
});*/
var center = svg.select('#node_' + nodes[0].id)
center.append("circle")
.attr("r", "14")
.style("fill","steelblue");
node.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
node.transition()
.attr("r", function(d) { return d.children ? 4.5 : Math.sqrt(d.size) / 10; });
// Exit any old nodes.
node.exit().remove();
}
function tick() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
// Toggle children on click.
function doubleclick(d) {
alert(d);
}
// 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;
}
render();
}
function mouseover() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 16);
}
function mouseout() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 8);
}
但是,我得到的(扩展后)是这样的:
<g class="node fixed" id="1063" transform="translate(329.44373878271944,118.27604414379978)" r="NaN"><image xlink:href="../img/icon-location.png" x="-8" y="-8" width="16" height="16"></image><text x="12" dy=".35em">PRO</text><image xlink:href="../img/icon-location.png" x="-8" y="-8" width="16" height="16"></image><text x="12" dy=".35em">Dropbox</text></g>
有什么帮助吗?
【问题讨论】:
-
另外,每次您点击“simon simon”时,它都会在我上面发布的同一个 html 中不断添加更多的文本项。
-
您似乎主要将元素附加到更新选择
node。您可能想改用node.enter()。 -
但我愿意....见下文。你可以说得更详细点吗? node.enter().append("g") .attr("class", "node") .attr("id", function(d) { return d.id; }) .on("click", click ) .on("dblclick", 双击) .on("mouseover", mouseover) .on("mouseout", mouseout) .call(force.drag);
-
在上面的代码中,你做例如
node.append("text")在render()。 -
我是 D3 的新手,我还在学习进入/退出的概念。你能发布一些你建议如何解决这个问题的衬里吗?谢谢!'
标签: javascript svg d3.js force-layout