我要求这不要让代码正常工作,但要确保我正确理解d3。我创建了一个d3条形图示例,我用它来更好地理解d3的数据绑定和更新模式。小提琴在这里:http://jsfiddle.net/qP9j9/22/
小提琴最好地解释了这个问题,但我也会在下面尝试解释:
我已将数据绑定和视图拆分为两个独立的函数:
var updateData = function() {
data = generateRandomData();
chart = d3.select('.chart').selectAll('div').data(data);
y = d3.scale.linear().domain([0, Math.floor(d3.max(data))]).range([1,300]);
updateChart();
};
var updateChart = function() {
var margin = 1;
var barWidth = (parseInt(d3.select('.chart').style('width'))/15) - margin;
chart.transition()
.style('height', function(d) { return y(d) + 'px' })
.style('width', function() { return barWidth + 'px' })
.style('left', function(d, i) { return (i * (barWidth+margin)) + 'px' });
chart.enter().append('div')
.style('height', function() { return 0; })
.style('width', function() { return barWidth + 'px' })
.style('left', function(d, i) { return (i * (barWidth+margin)) + 'px' })
.transition()
.style('height', function(d) { return y(d) + 'px' });
chart.exit().remove();
};
在调整大小时,我正在运行updateChart函数。我的想法是,当它没有改变时我宁愿不绑定数据,只需更新视图。当数据实际发生变化时,我运行updateData函数。
奇怪的是,updateData函数需要运行两次才能使事情正常工作。如果只调用updateData一次(当页面首次加载时),那么当updateChart运行时,enter()函数会再次附加数据。因此,当页面调整大小时,您只需获得重复的dom元素。
我已经尽可能地研究了这个问题,包括查看一些建议的“类似问题”,我当然可以轻松地“解决”这个问题。但感觉有一些基本的我不理解。
答案 0 :(得分:1)
D3背后的主要思想是链接数据和文档,因此将两者分开是一个坏主意,就像你已经完成的那样。特别是,您正在使用.enter()
和.exit()
选项,如果您之前未明确绑定数据,则这些选择无法正常运行。在您的情况下,.enter()
选项包含先前的选择,这就是为什么所有内容都被添加两次。
我的建议是两个一个功能更新,而不是两个单独的功能。如果您确实想要将它们分开,则需要在.enter()
函数中处理.exit()
和updateData()
选项,因为我已经在您更新过的小提琴{{1}} {{1}} 3}}