I have created a force layout using d3 and it works well. My initial data is loaded from a json file and the chart is drawn with techniques that are similar to this d3.js example:
Now that the chart is on the screen I need to add, update and remove nodes on the fly from data I receive over a web-socket. I have add and remove methods working, but I can't find the correct way to update an existing node's properties.
From the reading I have undertaken I gather the correct technique is to change the data source, then update the chart by using the enter() method.
To update a node I am doing the following:
function updateNode(id, word, size, trend, parent_id){
var updateNode = nodes.filter(function(d, i) { return d.id == id ? this : null; });
if(updateNode[0]){
updateNode.size = Number(size);
updateNode.trend = trend;
nodes[updateNode.index] = updateNode;
update();
}
}
The update function then updates the nodes with:
function update(){
node = vis.selectAll('.node')
.data(nodes, function(d) {
return d.id;
})
createNewNodes(node.enter());
node.exit().remove();
force.start();
}
function createNewNodes(selection){
var slct = selection.append('g')
.attr('class', 'node')
.call(force.drag);
slct.append('circle')
.transition()
.duration(500)
.attr('r', function(d) {
if(d.size){
return Math.sqrt(sizeScale(d.size)*40);
}
})
}
Am I taking the right approach to this? When I try this code the node I get as the datum when trying to set the radius attribute on the circle is the last node in the nodes array. I.e. the one that contains the hierarchical node data rather than a single node object.
Any pointers would be greatly appreciated, I've spent too much time on this :)