4

In the answer Mike posted here, he overviews three different ways to apply a change to a matched element based on a index or custom filter. I'm trying to clarify, hopefully for more people than just myself, the actual selections in these solutions.

So given a document with 6 SVG rects with class .bar, we have these different selections and what they return:

d3.select(".bar"):

[Array[1]  
0: rect.[object SVGAnimatedString]  
length: 1  
parentNode: html  
__proto__: Array[0]  

d3.selectAll(".bar"):

[Array[6]  
0: rect.[object SVGAnimatedString]  
1: rect.[object SVGAnimatedString]  
2: rect.[object SVGAnimatedString]  
3: rect.[object SVGAnimatedString]  
4: rect.[object SVGAnimatedString]  
5: rect.[object SVGAnimatedString]  
length: 6  
parentNode: html  
__proto__: Array[0]  

$(".bar"):

[
<rect class=​"dataBars" x=​"53.191489361702125" width=​"212.7659574468085" y="4.761904761904762" height=​"11.11111111111111">​&lt;/rect>​,  
<rect class=​"dataBars" x=​"74.46808510638297" width=​"372.3404255319149" y=​"20.634920634920636" height=​"11.11111111111111">​&lt;/rect>​, 
<rect class=​"dataBars" x=​"127.6595744680851" width=​"212.7659574468085" y=​"36.507936507936506" height=​"11.11111111111111">​&lt;/rect>,​  
<rect class=​"dataBars" x=​"31.914893617021274" width=​"212.7659574468085" y=​"52.38095238095238" height=​"11.11111111111111">​&lt;/rect>​,  
<rect class=​"dataBars" x=​"159.5744680851064" width=​"265.9574468085106" y=​"68.25396825396825" height=​"11.11111111111111">​&lt;/rect>​,  
<rect class=​"dataBars" x=​"234.04255319148936" width=​"138.29787234042553" y=​"84.12698412698413" height=​"11.11111111111111">​&lt;/rect>​,
]  

Now here's where it get's more tricky (for me at least), say I want to apply a style to the 3rd rectangle, this rectangle can be found using

d3.selectAll(".bar")[0][2]  

But if we want to then use the d3.selection.attr(), that returns

TypeError: Property 'style' of object #<SVGRectElement> is not a function

But we can then wrap this selection

d3.select(d3.selectAll(".bars rect")[0][2]).style("fill", "red")

and this will work as expected.

Then, if we want to apply a filter, such as

filter(function (d) { return d === 5 || d === 15;}

the d3.selectAll(".bar") must be used, and d3.select(d3.selectAll(".bar")) will not work correctly.

I've read Mike's excellent tutorials and documentation on selections, but just when I think I have it figured out, something pops up and surprises me. So what is the difference between these selections, and how do I know which one to use when? Thank you very much, and sorry for the long post!

4

2 回答 2

5

我过去曾尝试过这样做并遇到类似的错误。然后我意识到我并没有真正遵循预期的 API。您开始按索引访问选择元素的第二个,您就远离了人迹罕至的道路。

查看嵌套选择

所以,如果你想设计你的第三个酒吧,你会做

d3.selectAll(".bar").style("color", function(d,i) { return i === 2 ? "red" : null; } )

如果您的选择比这更嵌套一层,function(d,i,j)请进行此操作并同样从那里开始。等等。

于 2013-07-23T18:46:11.310 回答
3

通常,您不应通过索引访问返回选择的元素,而应过滤或使用子选择。这样,您可以.attr()毫无问题.atyle()地申请。这样做的原因是 D3 不返回 DOM 元素的“纯”数组(像 jquery 那样),而是支持 D3 操作的包装器中的元素。不过,它的行为仍然有点像一个数组——如果你对它进行索引,你会得到一个“纯”的 DOM 元素。你也可以给一个 DOM 元素d3.select(),它会在这个元素周围生成一个包装器,以启用所有 D3 的东西。

如果您查看 的文档filter(),您会发现一些有关如何使用它和子选择的示例。例如,您可以使用这些技术来获取选择的第三个元素。仅当您将数据绑定到要过滤的对象时,使用该.filter()函数才有意义,否则子选择应该做您想要的。

于 2013-07-23T18:42:43.217 回答