D3强制布局通过引用绑定变得不同步

时间:2016-03-30 00:46:27

标签: javascript d3.js graph javascript-objects

我有一个力布局,我可以动态添加节点。

TL; DR:我的图形数据绑定似乎在节点和链接之间失去同步。是否有任何设置强制图的示例,其中使用对象引用而不是ID或名称来动态添加和减少节点

我见过的所有示例都使用ID来映射节点和链接,但文档说(强调添加):

  

注意:源和目标属性的值最初可能   指定为nodes数组的索引;这些将被替换为   调用启动后的引用。

在我的例子中,我有一个Node类和一个包含节点和链接的Link类。链接具有对节点的实际引用,因此我假设我不必再做任何关联节点和链接的事情。

力量网络在布局网络方面做得很好。但似乎给定link.source和link.target中的节点不是应该存在的节点,这导致我对d3绑定的假设不正确。我是否未能在部队机制中设置(或重置)一些全局状态?

我的图表更新代码如下:

GraphView.prototype.updateGraph = function(graph) {
var graph_view = this;

// restart the force layout
this.force
    .nodes(graph.nodes)
    .links(graph.links);

// update the links
this.link_selection = this.link_selection.data(graph.links);
this.link_selection.exit().remove();
this.link_selection.enter()
    .append("svg:path")
    .attr("class", "link");

// update the nodes
this.node_selection = this.node_selection.data(graph.nodes);
this.node_selection.exit().remove();
var node_enter = this.node_selection.enter()
    .append("g")
    .attr("class", "node")
    .on('mouseover', this._showTooltip.bind(this))
    .on('mouseout', this._hideTooltip.bind(this))
    .on('click', this._selectNode.bind(this))
    .on('mousedown', this._handleMouseDown.bind(this))
    .on("contextmenu", function(data, index) { graph_view._showContextMenu(data, index); })
    .call(this.force.drag);

// create outer circle
node_enter
    .append("circle")
    .attr("class", "annulus")
    .style('fill', function(d) { return graph_view.nodeColor(d); })
    .style('r', function(d) { return graph_view.nodeRadius(d); })
    .attr("x", 0)
    .attr("y", 0);

// start ticking...
this.force.start();
};

tick方法:

GraphView.prototype._tick = function(e) {
this.link_selection
    .attr("d", function(d) {
    var dx = d.target.x - d.source.x;
    var dy = d.target.y - d.source.y;
    var dr = Math.sqrt(dx * dx + dy * dy);
    return "M " + d.source.x + " " + d.source.y +
        " A " + dr + " " + dr + " 0 0 1 "
        + d.target.x + " " + d.target.y;
    });
this.node_selection
    .attr('transform', function(d) {
    return 'translate(' + d.x + ',' + d.y + ')' });
};

1 个答案:

答案 0 :(得分:0)

我想我明白发生了什么。

首先,我没有看到任何使用d3.layout.force的对象引用的例子的原因是因为它不能工作:关联链接和节点的机制要求每个链接和每个节点提供一个不可变的句柄,即一个id。 (是的,您可以使用数组索引,但这是一个不同的问题)。

稍微令人惊讶的是,不可变句柄可以是任何东西,只要它对应的节点或链接是唯一的。实际上,不需要在节点id和链接id之间建立任何关系 - 这些只在设置数组索引时使用。

我希望有人提供更完整的答案,以便我给出一个复选标记。但如果他们不这样做,我会尝试提供更完整的描述。它有点神奇,但不是完全魔法。