1
我有一個相當簡單的可重複使用的圖表,內置D3.js - 一些圈子和一些文本。d3.js:爲什麼數據沒有更新?
我很努力地弄清楚如何在不重繪整個圖表的情況下使用新數據更新圖表。
使用當前腳本,我可以看到新數據綁定到svg元素,但沒有任何數據驅動的文本或屬性正在更新。 爲什麼不更新圖表?
這裏有一個小提琴:http://jsfiddle.net/rolfsf/em5kL/1/
我打電話這樣的圖表:
d3.select('#clusters')
.datum({
Name: 'Total Widgets',
Value: 224,
Clusters: [
['Other', 45],
['FooBars', 30],
['Foos', 50],
['Bars', 124],
['BarFoos', 0]
]
})
.call(clusterChart());
當單擊該按鈕時,我只是再次調用圖表,不同數據:
$("#doSomething").on("click", function(){
d3.select('#clusters')
.datum({
Name: 'Total Widgets',
Value: 122,
Clusters: [
['Other', 14],
['FooBars', 60],
['Foos', 22],
['Bars', 100],
['BarFoos', 5]
]
})
.call(clusterChart());
});
圖表腳本:
function clusterChart() {
var width = 450,
margin = 0,
radiusAll = 72,
maxRadius = radiusAll - 5,
r = d3.scale.linear(),
padding = 1,
height = 3 * (radiusAll*2 + padding),
startAngle = Math.PI/2,
onTotalMouseOver = null,
onTotalClick = null,
onClusterMouseOver = null,
onClusterClick = null;
val = function(d){return d};
function chart(selection) {
selection.each(function(data) {
var cx = width/2,
cy = height/2,
stepAngle = 2 * Math.PI/data.Clusters.length,
outerRadius = 2*radiusAll + padding;
r = d3.scale.linear()
.domain([0, d3.max(data.Clusters, function(d){return d[1];})])
.range([50, maxRadius]);
var svg = d3.select(this).selectAll("svg")
.data([data])
.enter().append("svg");
//enter
var totalCircle = svg.append("circle")
.attr("class", "total-cluster")
.attr('cx', cx)
.attr('cy', cy)
.attr('r', radiusAll)
.on('mouseover', onTotalMouseOver)
.on('click', onTotalClick);
var totalName = svg.append("text")
.attr("class", "total-name")
.attr('x', cx)
.attr('y', cy + 16);
var totalValue = svg.append("text")
.attr("class", "total-value")
.attr('x', cx)
.attr('y', cy + 4);
var clusters = svg.selectAll('circle.cluster')
.data(data.Clusters)
.enter().append('circle')
.attr("class", "cluster");
var clusterValues = svg.selectAll("text.cluster-value")
.data(data.Clusters)
.enter().append('text')
.attr('class', 'cluster-value');
var clusterNames = svg.selectAll("text.cluster-name")
.data(data.Clusters)
.enter().append('text')
.attr('class', 'cluster-name');
clusters .attr('cx', function(d, i) { return cx + Math.cos(startAngle + stepAngle * i) * outerRadius; })
.attr('cy', function(d, i) { return cy + Math.sin(startAngle + stepAngle * i) * outerRadius; })
.attr("r", "10")
.on('mouseover', function(d, i, j) {
if (onClusterMouseOver != null) onClusterMouseOver(d, i, j);
})
.on('mouseout', function() { /*do something*/ })
.on('click', function(d, i){ onClusterClick(d); });
clusterNames
.attr('x', function(d, i) { return cx + Math.cos(startAngle + stepAngle * i) * outerRadius; })
.attr('y', function(d, i) { return cy + Math.sin(startAngle + stepAngle * i) * outerRadius + 16; });
clusterValues
.attr('x', function(d, i) { return cx + Math.cos(startAngle + stepAngle * i) * outerRadius; })
.attr('y', function(d, i) { return cy + Math.sin(startAngle + stepAngle * i) * outerRadius - 4; });
//update with data
svg .selectAll('text.total-value')
.text(val(data.Value));
svg .selectAll('text.total-name')
.text(val(data.Name));
clusters
.attr('class', function(d, i) {
if(d[1] === 0){ return 'cluster empty'}
else {return 'cluster'}
})
.attr("r", function (d, i) { return r(d[1]); });
clusterValues
.text(function(d) { return d[1] });
clusterNames
.text(function(d, i) { return d[0] });
$(window).resize(function() {
var w = $('.cluster-chart').width(); //make this more generic
svg.attr("width", w);
svg.attr("height", w * height/width);
});
});
}
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.onClusterClick = function(_) {
if (!arguments.length) return onClusterClick;
onClusterClick = _;
return chart;
};
return chart;
}
非常感謝你@FernOfTheAndes花時間重新編寫小提琴並讓它工作。我開始嘗試將「進入」和「更新」分開,但從未完全理解「退出」。我同意svg:g元素 - 我原來使用它,但是當事情沒有奏效時,我就擺脫了它。再次感謝! – rolfsf
關於svg:g方法的後續問題 - 如果我將總計元素放在他們自己的組中,我只需要在「g」上執行.exit.remove(),而不是每個元素(文本,圓) ? – rolfsf
@rolfsf是的,非常。我繼續在我的年輕人中創建了一篇文章:) [博客](http://fernoftheandes.com/blog/)。如果解釋清楚,請讓我知道。謝謝! – FernOfTheAndes