D3 circle pack - динамическое обновление этикетки
Я довольно новичок в кодировании в D3. Я работаю над круговой диаграммой почти в реальном времени, которая получает базовые данные от вызова ajax и изменяет размеры узлов на основе изменений в значениях данных. Задача, с которой я сталкиваюсь, вероятно, будет ужасно простой, но я пока не нашел достаточно похожего примера в Интернете, чтобы использовать его в качестве решения.
Когда я запускаю этот код, я знаю, что текстовые значения действительно передаются должным образом при изменении данных. Однако происходит следующее: код продолжает добавлять текстовые теги к узлам svg "g" (с обновленными значениями), а не изменяет существующий элемент для отображения обновленного значения. Результатом является многослойный текстовый беспорядок в середине иначе привлекательного пузыря.
Я пытался использовать d3.exit().remove()
безрезультатно - возможно, что я неправильно использовал это и что это действительно подходящая техника для применения.
Будет ли кто-то готов дать несколько советов о том, как мне выполнить 2 конкретные вещи:
1) Я хотел бы повторно использовать существующие "текстовые" элементы вместо удаления + добавления, если это не практично.
2) Я хотел бы обновить значения существующего "текстового" элемента новыми данными, не обновляя страницу.
Полный код файла.js приведен ниже. Я знаю, что могу использовать "svg" вместо "svg: svg" и т. Д., Но я еще не дошел до стадии очистки этого файла.
var Devices = {
setup_devices : function() {
var r = 500,
format = d3.format(",d"),
fill = d3.scale.category10();
var bubble = d3.layout.pack()
.sort(null)
.size([r, r])
.padding(1.5);
var chart = d3.select("#device_info").append("svg:svg")
.attr("width", r)
.attr("height", r)
.attr("class", "bubble")
.append("svg:g")
.attr("transform", "translate(2, 2)");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Device:</strong> <span style='color:red'>" + d.name + "</span>";
});
chart.call(tip);
setInterval(function() {
console.log("Devices Refreshing");
$.ajax({
type: "GET",
url: "/devices",
dataType: "json",
beforeSend: function() {
},
error: function( jqXHR, textStatus, thrownError ) {
return true;
},
success: function(data) {
update(data);
return true;
}
});
d3.timer.flush();
}, 2000);
function update(data) {
var updated = chart.data([data]).selectAll("g.node")
.data(bubble.nodes);
updated.enter().append("svg:g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("data-name", function(d) {
return d.name;
})
.attr("data-device", function(d) {
return d.device_id;
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.append("svg:circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return fill(d.name); })
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text(function(d) { return d.value + "%" });
updated.append("svg:text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text(function(d) { return d.value + "%" });
updated.transition()
.duration(1000)
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
updated.select("circle").transition()
.duration(1000)
.attr("r", function(d) { return d.r; })
.text(function(d) { return d.value + "%" });
}
}
}
1 ответ
Вам просто нужно обрабатывать выбор ввода и обновления отдельно - к добавляемой выборке ввода, для выбора обновления вы повторно используете существующие элементы.
var enterGs = updated.enter().append("svg:g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("data-name", function(d) {
return d.name;
})
.attr("data-device", function(d) {
return d.device_id;
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
enterGs.append("circle");
enterGs.append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em");
updated.select("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return fill(d.name); });
updated.select("text")
.text(function(d) { return d.value + "%" });