【发布时间】:2015-06-23 21:48:00
【问题描述】:
我正在做一个 d3js 副项目,我正在使用强制布局来显示节点和线来表示图形。我已经布置了代码,以便可以动态更新图形。我这样做是:
- 清除 force.nodes() 然后 force.links()
- 将我要添加的所有节点推送到 force.nodes()
- 更新图表(加入、进入、更新、退出)
- 将我想要的所有链接与 force.nodes() 中节点的引用一起推送到 force.links
- 更新图表(加入、进入、更新、退出)
只要我只有要显示的节点,它就可以工作,但是一旦我尝试将链接推送到 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}
]
}
【问题讨论】:
-
你的数据是什么样的?
-
@StephenThomas 数据已添加到帖子中
-
如果用
var c = {"source": 0, "target": 1}替换麻烦的语句会发生什么?我不确定 D3 是否可以处理将索引与对象引用混合的初始链接数组。 -
它应该能够按照文档使用引用。索引只是为了方便加载 JSON 数据。模拟开始后,d3 将这些索引替换为对它们所代表的对象的引用。我也知道它应该可以工作,因为我的代码基于这个块:bl.ocks.org/ericcoopey/6c602d7cb14b25c179a4
-
添加链接后需要运行
force.start()。每次更改节点或链接的结构时,都必须重新开始布局。这将根据新数据初始化一些数组。如果您不这样做,force.tick()方法将在其计算中遇到一些未定义的值,这就是 NaN 的来源。
标签: javascript d3.js