Как обновить элементы макета силы D3 при изменении базовых данных
Я использую один из примеров компоновки силы (http://bl.ocks.org/1153292), чтобы показать сеть на моем веб-сайте.
Я разрешаю пользователю выбирать, какие типы ссылок будут отображаться в любой момент времени. Я замечаю, что когда я выбираю тип ссылки A, затем добавляю тип ссылки B, а затем удаляю тип ссылки A, оставшиеся ссылки типа B представлены цветами A.
Это код, который запускается для добавления ссылок на диаграмму svg. Я меняю массив this.links
, добавляя и удаляя ссылки из него. Как вы видите, я устанавливаю атрибут класса, но он не обновляется - он остается от типа ссылки A.
var path = svg.append("svg:g")
.selectAll("path")
.data(this.links)
.enter()
.append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
В настоящее время я работаю над этой проблемой, обновляя атрибут класса внутри функции tick, но этот курс не требует много работы.
Я прочитал, что операция ввода возвращает объединенный выбор существующих элементов, а также новые, поэтому операция attr должна обновлять существующую и устанавливать новую.
Что мне не хватает?
Ответы
Ответ 1
Я нашел ответ в этом сообщении
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr("r", 2.5);
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circle.exit().remove();
Ответ заключается в том, что мне нужно вызвать оператор attr на результат selectAll.data, а не на результат оператора append.
Ответ 2
В http://bl.ocks.org/1095795 есть пример, показывающий добавление и удаление узлов из направленного по силе макета. Связи и узлы должны обрабатываться отдельно, а затем необходимо повторно запустить компоновку сил.
function restart() {
var link = vis.selectAll("line.link")
.data(links, function(d) { return d.source.id + "-" + d.target.id; });
link.enter().insert("svg:line", "g.node")
.attr("class", "link");
link.exit().remove();
var node = vis.selectAll("g.node")
.data(nodes, function(d) { return d.id;});
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
nodeEnter.append("svg:image")
.attr("class", "circle")
.attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
.attr("x", "-8px")
.attr("y", "-8px")
.attr("width", "16px")
.attr("height", "16px");
nodeEnter.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.id });
node.exit().remove();
force.start();
}