修改d3.js中的节点和边缘属性

时间:2013-02-16 06:05:08

标签: d3.js force-layout

我正在使用d3.js使用强制布局布局节点和链接图。节点用圆圈表示;按行链接。在某些情况下,我想改变线或节点的视觉特性(例如,颜色,大小,不透明度等)以表示图上的一些状态变化。我已经能够通过重新绘制图形来实现这一点,但是这会使所有节点发生抖动,从而导致混淆而不是清晰。

创建图表的代码:

force = d3.layout.force()
        .charge(-120)
        .gravity(0.2)
        .linkDistance(30)
        .size([width-pad, height-pad]);


nodeSet = svg.selectAll(".qNode");
// BIND NODE DATA
nodeSet = nodeSet.data(chartData.nodes);
// CREATE NODES
nodeSet.enter().append("circle")
    .attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style('stroke-opacity', function(d) { return d.opacity(); })
    .style('stroke', function(d) { return d.color(); })
    .style("fill", function(d) { return color(1); });
//similarly for links.

force.nodes(chartData.nodes).links(chartData.links).start();

要更新图表,我使用此片段:

    // SELECT NODES
    nodeSet = svg.selectAll('.qNode');
    // JOIN NODES
    nodeSet = nodeSet.data(force.nodes());
    // UPDATE NODES
    nodeSet.attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style("fill", function(d) { return color(1); })
    .style('stroke', function(d) { return d.color(); })
    .style('stroke-opacity', function(d) { return d.opacity(); })
    .style('opacity', 1)
    .call(force.drag);
    // CREATE NODES
    nodeSet.enter().append("circle")
    .attr("class", "qNode")
    .attr("r", function(d) { return d.size();})
    .style("fill", function(d) { return color(1); })
    .call(force.drag);
    // DELETE NODES
    nodeSet.exit().remove();


    // START SHOW
    force.start();

当它运行时,整个图形会稍微摇晃一下,然后再应用新的笔触属性。

所以我有两个问题:假设数据对象中的状态更改将返回d.size()d.color()等的不同值,

  1. 如何在不摇晃任何节点的情况下修改图形的外观?
  2. 如果我想摇动节点,我可以确定哪些节点要摇晃? (这样我就可以向用户发出哪个链接节点的视觉外观发生变化的信号。)
  3. EDITED

    我暂时放弃了对节点的抖动,但下面的代码(基于@defenestrated的建议)似乎可以更新图中某些节点和边缘的属性:

    var allLinks = ... // my links from a d3 selectAll
    var allNodes = ... // my nodes from a d3 selectAll
    force = ... // my d3 force layout
    function updateGraph(graph, nodeSubset, linkSubset) {
        for (var i=0; i<allLlinks.length; i++)
            allLinks[i].selected = false;
        for (var i=0; i<allNodes.length; i++)
            allNodes[i].selected = false;
        for (var i=0; i<linkSubset.length; i++)
            linkSubset[i].selected = true;
        for (var i=0; i<nodeSubset.length; i++)
             nodeSubset[i].selected = true;
    
        // these functions modify the selected nodes and links
        linkSubset.call(setLinkAttributes);
        nodeSubset.call(setNodeAttributes);
    
        if (force.alpha() == 0) {
            force.start();
            force.stop();
        }
    }
    
    function setLinkAttributes(links) {
        link.style(...);
    }
    
    function setNodeAttributes(nodes) {
        nodes.style(...);
    }
    

    如果图表在应用属性后仍在移动(如果start),则无需致电stop / resumealpha() > 0新属性。如果图表已经稳定,则调用start会刷新它而不移动节点。

1 个答案:

答案 0 :(得分:1)

  1. 您是否尝试在“更新节点”块之前调用force.stop(),并在{1}之后调用{<1}}?

  2. 您可以根据其状态对它们进行分类 - 因此您将force.resume()应用于正在更新的节点,然后在d3选择中使用它,例如。 changedNodes = .attr("id", "changed")