片段1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
</head>
<body>
<script type="text/javascript">
var data = [];
for (i = 0; i < 3; i += 1) {
data.push(i);
}
d3.select('body')
// .selectAll('p')
.data(data)
.enter()
.append('p')
.text(function(d) {
return d;
});
</script>
</body>
</html>
片段2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
</head>
<body>
<script type="text/javascript">
var data = [];
for (i = 0; i < 3; i += 1) {
data.push(i);
}
d3.select('body')
.selectAll('p')
.data(data)
.enter()
.append('p')
.text(function(d) {
return d;
});
</script>
</body>
</html>
代码
.selectAll('p')
在第一个代码段中被注释。由于这一原因,我无法弄清为什么忽略第一个数据。我是d3.js的新手,据我了解,由于我的HTML中没有
p
标记,因此.selectAll('p')
返回空选择,并且根据我的数据计数附加了p
。提前致谢。
最佳答案
要了解发生了什么,您必须了解什么是“输入”选择。这篇文章底部的示例简要说明了“输入”选择以及为什么在第二个代码段中都必须selectAll("p")
的原因,即使您在文档中没有任何<p>
。
现在,让我们看看您的片段:
您的第一个片段:
在您的第一个代码段中,data
是[0, 1, 2]
。因此,您有3个元素。选择主体时,DOM中显然有一个body
。因此,将第一个基准(0)关联到该元素(主体)。现在,您有2个未与任何DOM元素关联的数据:1
和2
。这两个数据是您的“输入”选择。附加<p>
时,您的输入选择仅包含这两个数字。
你的第二个片段
在第二个片段中,数据再次为[0, 1, 2]
。区别在于,现在您选择了所有<p>
...,但是没有一个。这是我链接的示例中的“占位符”。由于DOM中没有与数据关联的<p>
,因此您的回车选择具有所有3个数据:0
,1
和2
。
如我在示例中所写:
如果在“输入”选择中选择了不存在的内容,则“输入”选择将始终包含所有数据。
占位符在“输入”选择中的作用
什么是回车选择?
在D3.js中,当一种将数据绑定到DOM元素时,可能出现三种情况:
元素数和数据点数相同;
元素多于数据点;
数据点多于元素。
在情况#3中,所有没有相应DOM元素的数据点都属于enter选择。因此,在D3.js中,输入选择是将元素连接到数据后包含与任何DOM元素都不匹配的所有数据的选择。如果我们在回车选择中使用append
函数,则D3将为我们创建绑定该数据的新元素。
这是一个维恩图,解释有关数据点数量/ DOM元素数量的可能情况:
如我们所见,回车选择是左侧的蓝色区域:没有相应DOM元素的数据点。
回车选择的结构
通常,回车选择包括以下四个步骤:selectAll
:选择DOM中的元素;data
:计算并分析数据;enter
:将选择内容与数据进行比较,创建新元素;append
:在DOM中附加实际元素;
这是一个非常基本的示例(请查看var divs
中的4个步骤):
var data = [40, 80, 150, 160, 230, 260];
var body = d3.select("body");
var divs = body.selectAll("div")
.data(data)
.enter()
.append("div");
divs.style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
这是结果(jsfiddle here):
请注意,在这种情况下,我们将
selectAll("div")
用作“输入”选择变量的第一行。我们有一个包含6个值的数据集,而D3为我们创建了6个div。占位符的作用
但是,假设我们的文档中已经有一个div,例如
<div>This is my chart</div>
在顶部。在这种情况下,当我们写:body.selectAll("div")
我们正在选择存在的div。因此,我们的回车选择将只有5个没有匹配元素的原点。例如,in this jsfiddle,HTML中已经有一个div(“这是我的图表”),结果如下:
我们不再看到值“ 40”:我们的第一个“小节”消失了,原因是我们的“输入”选择现在只有5个元素。
我们在这里要了解的是,在我们的输入选择变量
selectAll("div")
的第一行中,这些div只是占位符。如果要添加divs
,则不必选择所有divs
;如果要添加circle
,则不必选择所有circle
。我们可以选择不同的东西。而且,如果我们不打算进行“更新”或“退出”选择,则可以选择任何内容:var divs = body.selectAll(".foo")//this class doesn't exist, and never will!
.data(data)
.enter()
.append("div");
这样,我们选择所有的“ .foo”。在这里,“ foo”是一个不仅不存在的类,而且从未在代码的其他任何地方创建!但这并不重要,这只是一个占位符。逻辑是这样的:
如果在“输入”选择中选择了不存在的内容,则“输入”选择将始终包含所有数据。
现在,选择
.foo
,即使我们在文档中已经有一个div,我们的“输入”选择也包含6个元素:这是corresponding jsfiddle。
选择
null
到目前为止,确保您什么都不做的最好方法是选择
null
。不仅如此,而且这种替代方法比其他方法都快。因此,对于回车选择,只需执行以下操作:
selection.selectAll(null)
.data(data)
.enter()
.append(element);
这是一个演示小提琴:https://jsfiddle.net/gerardofurtado/th6s160p/
结论
处理“输入”选择时,请格外小心,不要选择已经存在的内容。您可以使用
selectAll
中的任何内容,甚至可以使用不存在且永远不存在的内容(如果您不打算进行“更新”或“退出”选择)。示例中的代码基于Mike Bostock的以下代码:https://bl.ocks.org/mbostock/7322386
关于javascript - 无需在d3.js中使用selectAll即可忽略第一个数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38810938/