如果不在d3.js中使用selectAll,则忽略第一个数据

时间:2016-08-07 04:43:18

标签: javascript jquery html d3.js

Snippet 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>

Snippet 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根据我的数据计算。

提前致谢。

1 个答案:

答案 0 :(得分:2)

要了解发生了什么,你必须了解什么是&#34;输入&#34;选择。本文底部的例子简要解释了&#34;输入&#34;选择以及为什么必须在第二个代码段中selectAll("p"),即使您在文档中没有<p>

现在,让我们看一下你的片段:

您的第一个代码

在您的第一个代码段中,data[0, 1, 2]。所以,你有3个元素。选择正文时,DOM中显然有body。因此,您将第一个数据(0)与此元素(正文)相关联。现在,您有2个与任何DOM元素无关的数据:12。这两个数据是你的&#34;输入&#34;选择。当您追加<p>时,您的输入选择只包含这两个数字。

您的第二个代码段

在您的第二个代码段中,数据再次为[0, 1, 2]。不同的是,现在您选择了所有<p> ...但没有。这是&#34;占位符&#34;在我链接的示例中。由于DOM中没有<p>与数据相关联,因此您的输入选择包含所有3个数据:012

正如我在例子中写的那样:

  

如果在你的&#34;输入&#34;选择你选择的东西,你的&#34;输入&#34;选择将始终包含您的所有数据。

占位符在&#34;输入&#34;选择

什么是输入选择?

在D3.js中,当一个人将数据绑定到DOM元素时,有三种情况可能:

  1. 元素数量和数据点数相同;
  2. 元素多于数据点;
  3. 数据点多于元素;
  4. 在情况#3中,没有相应DOM元素的所有数据点都属于 enter 选择。因此,在D3.js中,输入选择是在将元素连接到数据之后包含不与任何DOM元素匹配的所有数据的选择。如果我们在输入选项中使用append函数,D3将为我们创建绑定该数据的新元素。

    这是一个维恩图,解释了有关数据点数/ DOM元素数的可能情况:

    enter image description here

    正如我们所看到的,输入选项是左侧的蓝色区域:没有相应DOM元素的数据点。

    输入选择的结构

    通常,输入选项包含以下4个步骤:

    1. selectAll:选择DOM中的元素;
    2. data:计算和解析数据;
    3. enter:将选择与数据进行比较,创建新元素;
    4. append:在DOM中附加实际元素;
    5. 这是一个非常基本的例子(请查看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):

      enter image description here

      请注意,在这种情况下,我们使用selectAll("div")作为我们&#34;输入&#34;的第一行。选择变量。我们有一个包含6个值的数据集,D3为我们创建了6个div。

      占位符的作用

      但是假设我们的文档中已经有一个div,顶部是<div>This is my chart</div>。在那种情况下,当我们写:

      body.selectAll("div")
      

      我们正在选择现有的div。因此,我们的输入选择将只有5个数据而没有匹配的元素。例如,in this jsfiddle,HTML中已有div(&#34;这是我的图表&#34;),这将是结果:

      enter image description here

      我们没有看到价值&#34; 40&#34;再来一次:我们的第一个&#34;酒吧&#34;消失了,其原因是我们进入&#34;进入&#34;现在选择只有5个元素。

      我们在这里要理解的是,在我们的输入选择变量的第一行selectAll("div")中,这些div只是占位符。如果我们要追加divs,则我们不必选择所有divs,如果我们追加circle,则不必选择所有circle。我们可以选择不同的东西。并且,如果我们不打算进行更新&#34;或者退出&#34;退出&#34;选择,我们可以选择任何

      var divs = body.selectAll(".foo")//this class doesn't exist, and never will!
          .data(data)
          .enter()
          .append("div");
      

      这样做,我们选择所有&#34; .foo&#34;。在这里,&#34; foo&#34;是一个不仅不存在的类,而且它从未在代码中的任何其他地方创建过!但这并不重要,这只是一个占位符。逻辑是:

        

      如果在你的&#34;输入&#34;选择你选择的东西,你的&#34;输入&#34;选择将始终包含您的所有数据。

      现在,选择.foo,我们的&#34;输入&#34;选择有6个元素,即使我们已经在文档中有一个div:

      enter image description here

      这是corresponding jsfiddle

      选择null

      到目前为止,保证您不做任何选择的最佳方法是选择null。不仅如此,这种替代方案比其他方式更快。<​​/ p>

      因此,对于输入选择,只需执行:

      selection.selectAll(null)
          .data(data)
          .enter()
          .append(element);
      

      这是一个演示小提琴:https://jsfiddle.net/gerardofurtado/th6s160p/

      <强>结论

      处理&#34;输入&#34;选择时,要特别注意不要选择已经存在的东西。您可以使用selectAll中的任何内容,即使是不存在且永远不存在的内容(如果您不打算进行&#34;更新&#34;或者&#34)退出&#34;选择)。

      示例中的代码基于Mike Bostock的代码:https://bl.ocks.org/mbostock/7322386