我正在开发一个d3js侧项目,我正在使用强制布局来显示节点和线来表示图形。我已经布置了代码,以便可以动态更新图形。我这样做是通过:
只要我只有节点可以显示,这就可以工作,但是一旦我尝试将链接推送到force.links,那么所有地狱都会松动,两个节点最终会隐藏在左上角。
查看DOM我可以看到以下内容:
如您所见,transform / translate参数包含NaN值。所以有些东西在我的脸上爆炸,但经过两天的虫子狩猎后,我怀疑我在这里遗失了一些东西,需要洗个冷水澡。
我已经将我的代码剥离到可以重现错误的最小集合。请注意,节点显示正常,直到链接被推入force.links。没有链接被绘制,只有节点,但推送它所属的链接的行为正在破坏节点中的数据。这种更新图表的方式应该按照我见过的例子工作。
d3.json("data/fm.json", function(error, graph) {
if (error) throw error;
function chart(elementName) {
// look for the node in the d3 layout
var findNode = function(name) {
for (var i in nodes) {
if (nodes[i]["name"] === name) return nodes[i];
};
};
var width = 960, // default width
height = 450, // default height
color = d3.scale.category10(),
force = d3.layout.force(),
nodes = force.nodes(),
links = force.links(),
vis,
runOnceFlag = true;
vis = d3.select(elementName)
.append("svg:svg")
.attr("width", width)
.attr("height", height)
.attr("id", "svg")
.attr("pointer-events", "all")
.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.append('svg:g');
var update = function() {
var node = vis.selectAll("g.node")
.data(nodes, function (d) {
return d.name;
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.call(force.drag);
nodeEnter.append("svg:circle")
.attr("r", 12)
.attr("id", function (d) {
return "Node;" + d.name;
})
.attr("class", "nodeStrokeClass")
.attr("fill", function(d) { return color(d.group); });
nodeEnter.append("svg:text")
.attr("class", "textClass")
.attr("x", 14)
.attr("y", ".31em")
.text(function (d) {
return d.name;
});
node.exit().remove();
force.on("tick", function () {
node.attr("transform", function (d) {
console.log(d);
return "translate(" + d.x + "," + d.y + ")";
});
});
// Restart the force layout.
force
.charge(-120)
.linkDistance( function(d) { return d.value * 10 } )
.size([width, height])
.start();
};
var a = graph.nodes[0];
var b = graph.nodes[1]
nodes.push(a);
update();
nodes.push(b);
update();
var c = {"source": findNode('a'), "target": findNode('b')}
// the line below causes the error
links.push(c);
update()
};
///
chart('body');
});
这是我的数据:
{
"nodes":[
{"name":"a", "group":1},
{"name":"b", "group":2},
{"name":"c", "group":3},
{"name":"d", "group":4},
{"name":"e", "group":5},
{"name":"f", "group":6},
{"name":"g", "group":7},
{"name":"h", "group":1},
{"name":"i", "group":2},
{"name":"j", "group":3},
{"name":"k", "group":4},
{"name":"l", "group":5},
{"name":"m", "group":6},
{"name":"n", "group":7}
],
"links":[
{"source":0,"target":1,"value":1},
{"source":2,"target":3,"value":1},
{"source":4,"target":5,"value":1},
{"source":7,"target":8,"value":1},
{"source":9,"target":10,"value":1},
{"source":11,"target":12,"value":1},
{"source":0,"target":5,"value":1},
{"source":1,"target":5,"value":1},
{"source":0,"target":6,"value":1},
{"source":1,"target":6,"value":1},
{"source":0,"target":7,"value":1},
{"source":1,"target":7,"value":1},
{"source":2,"target":8,"value":1},
{"source":3,"target":8,"value":1},
{"source":2,"target":9,"value":1},
{"source":3,"target":9,"value":1},
{"source":4,"target":11,"value":1},
{"source":5,"target":11,"value":1},
{"source":9,"target":12,"value":1},
{"source":10,"target":12,"value":1},
{"source":11,"target":13,"value":1},
{"source":12,"target":13,"value":1}
]
}
答案 0 :(得分:2)
您的代码存在一些基本问题,请参阅下面的corrected concept ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.link {
stroke: #2E2E2E;
stroke-width: 2px;
}
.node {
stroke: #fff;
stroke-width: 2px;
}
.textClass {
stroke: #323232;
font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
font-weight: normal;
stroke-width: .5;
font-size: 14px;
}
</style>
</head>
<body>
<!--<script src="d3 CB.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
d3.json("data.json", function (error, graph) {
if (error) throw error;
function chart(elementName) {
// look for the node in the d3 layout
var findNode = function (name) {
for (var i in nodes) {
if (nodes[i]["name"] === name) return nodes[i];
}
};
var width = 960, // default width
height = 450, // default height
color = d3.scale.category10(),
nodes = graph.nodes,
links = graph.links,
force = d3.layout.force()
.nodes(nodes)
.links([]),
vis,
runOnceFlag = true;
vis = d3.select(elementName)
.append("svg:svg")
.attr("width", width)
.attr("height", height)
.attr("id", "svg")
.attr("pointer-events", "all")
.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.append('svg:g');
var update = function () {
var link = vis.selectAll("line")
.data(force.links(), function (d) {
return d.source + "-" + d.target;
});
link.enter().insert("line", "g")
.attr("id", function (d) {
return d.source + "-" + d.target;
})
.attr("stroke-width", function (d) {
return d.value / 10;
})
.attr("class", "link")
.style("stroke", "red")
.transition().duration(5000).style("stroke", "black");
link.append("title")
.text(function (d) {
return d.value;
});
link.exit().remove();
var node = vis.selectAll("g.node")
.data(nodes, function (d) {
return d.name;
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.call(force.drag);
nodeEnter.append("svg:circle")
.attr("r", 12)
.attr("id", function (d) {
return "Node;" + d.name;
})
.attr("class", "nodeStrokeClass")
.attr("fill", function (d) {
return color(d.group);
});
nodeEnter.append("svg:text")
.attr("class", "textClass")
.attr("x", 14)
.attr("y", ".31em")
.text(function (d) {
return d.name;
});
node.exit().remove();
force.on("tick", function () {
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) {
console.log(d);
return "translate(" + d.x + "," + d.y + ")";
});
});
// Restart the force layout.
force
.charge(-120)
.linkDistance(function (d) {
return d.value * 100
})
.size([width, height])
.start();
};
update();
var c = {"source": findNode('a'), "target": findNode('b'), value: 1}
// the line below causes the error
window.setTimeout(function() {
force.links().push(c);
update()
},2000)
};
//
chart('body');
});
</script>
</body>
</html>