我问这个不是为了让代码工作,而是为了确保我正确理解 d3。我创建了一个 d3 条形图示例,我用它来更好地理解 d3 的数据绑定(bind)和更新模式。 fiddle 在这里:http://jsfiddle.net/qP9j9/22/
fiddle 最好地解释了问题,但我也会尝试在下面进行解释:
我已将数据绑定(bind)和 View 拆分为两个单独的函数:
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 函数。我的想法是,我宁愿在数据不改变时不绑定(bind)数据,只更新 View 。当数据实际发生变化时,我运行 updateData 函数。
奇怪的是,updateData 函数需要运行两次才能正常工作。如果 updateData 只被调用一次(当页面首次加载时),那么当 updateChart 运行时,enter() 函数会重新附加数据。因此,当页面调整大小时,您只会得到重复的 dom 元素。
我已经尽可能多地研究了这个问题,包括查看了一些建议的“类似问题”,我当然可以很容易地“解决”这个问题。但感觉好像有一些基本的东西我不理解。
最佳答案
D3 背后的主要思想是链接数据和文档,因此像您所做的那样将两者分开是个坏主意。特别是,您正在使用 .enter()
和 .exit()
选择,如果您之前没有明确绑定(bind)数据,则无法正常工作。在你的例子中,.enter()
selection 包含之前的选择,这就是为什么所有内容都添加两次的原因。
我的建议是两个具有一个更新功能,而不是两个单独的。如果你真的想把它们分开,你需要处理 .enter()
和 .exit()
updateData()
中的选择功能,正如我在您更新的 fiddle 中所做的那样 here .
关于javascript - d3 - 输入 - 追加太多元素,就好像数据没有绑定(bind)一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20842666/