文章中定义的可重用图表可用于将图表插入任何 DOM 元素,可能在同一页面上多次插入,尽管使用不同的data
. 此外,由于您指出的声明,它可用于更新已存在于 DOM 元素中的图形。它的使用方式是(来自文章):
var formatDate = d3.time.format("%b %Y");
var chart = timeSeriesChart()
.x(function(d) { return formatDate.parse(d.date); })
.y(function(d) { return +d.price; });
// Put the chart _inside_ #example1
d3.select("#example1")
.datum(data1)
.call(chart);
// Put the same chart _inside_ #example2
d3.select("#example2")
.datum(data1)
.call(chart);
// Update the data for #example1, without appending another <svg> element
setInterval(function () {
d3.select("#example1")
.datum(data2)
.call(chart);
}, 5000);
现在解决您对它如何做到这一点的担忧:
首先注意这段代码是在里面运行的selection.each(...)
。根据 API 参考,.eachthis
中的上下文是 DOM 元素。API参考进一步说:
通过在回调函数中使用 d3.select(this),可以使用 each 运算符递归处理选择。
所以d3.select(this)
只返回一个d3.selection
只包含当前 DOM 元素的元素,它可能包含也可能不包含其中的<svg>
元素。选择页面上的一个/每个<svg>
元素不会产生一个非常可重用的图表,因为它会弄乱整个页面,而不仅仅是您希望图表出现的 DOM 元素。
使用selectAll
创建一个新的元素分组供 D3 处理,与select
保留原始分组相反。有关嵌套选择如何工作的更多详细信息,请参阅本文。而且,是的,您是对的,selectAll
这里的组将仅用于创建或更新一个<svg>
元素,这将我们带到了下一点。
D3 背后的一个基本概念是data-joins,其中数据数组以一对一的方式连接到一组 DOM 元素。在这种情况下,我们有兴趣将一些附加/更新到恰好一个元素。Using为我们提供了一个可以绑定到一个元素的单元素数组。或者,这可以写成:data
<svg>
[data]
<svg>
var svg = d3.select(this).selectAll("svg").data([1]); // No `data`
// Update the area path.
g.select(".area")
.data(data) // Specifying data explicitly
.attr("d", area.y0(yScale.range()[0]));
// Update the line path.
g.select(".line")
.data(data) // Specifying data explicitly
.attr("d", line);
但是,通过将数据绑定到元素,让子选择已经可以使用数据会更令人愉悦。<svg>