Я создал силовой макет с помощью d3, и он работает хорошо. Мои исходные данные загружаются из файла json, и диаграмма рисуется с использованием методов, аналогичных этот пример d3.js:
Теперь, когда диаграмма находится на экране, мне нужно добавлять, обновлять и удалять узлы на лету из данных, которые я получаю через веб-сокет. У меня работают методы добавления и удаления, но я не могу найти правильный способ обновить свойства существующего узла.
Из прочитанного я понял, что правильная техника состоит в том, чтобы изменить источник данных, а затем обновить диаграмму с помощью метода enter().
Чтобы обновить узел, я делаю следующее:
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();
}
}
Затем функция обновления обновляет узлы с помощью:
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);
}
})
}
Правильно ли я подхожу к этому? Когда я пробую этот код, узел, который я получаю в качестве точки отсчета при попытке установить атрибут радиуса для круга, является последним узлом в массиве узлов. т.е. тот, который содержит данные иерархического узла, а не один объект узла.
Любые указатели будут очень признательны, я потратил слишком много времени на это :)