javascript - 无需在d3.js中使用selectAll即可忽略第一个数据

标签 javascript jquery html d3.js

片段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元素关联的数据:12。这两个数据是您的“输入”选择。附加<p>时,您的输入选择仅包含这两个数字。

你的第二个片段

在第二个片段中,数据再次为[0, 1, 2]。区别在于,现在您选择了所有<p> ...,但是没有一个。这是我链接的示例中的“占位符”。由于DOM中没有与数据关联的<p>,因此您的回车选择具有所有3个数据:012

如我在示例中所写:


  如果在“输入”选择中选择了不存在的内容,则“输入”选择将始终包含所有数据。




占位符在“输入”选择中的作用

什么是回车选择?

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


元素数和数据点数相同;
元素多于数据点;
数据点多于元素。


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

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

enter image description here

如我们所见,回车选择是左侧的蓝色区域:没有相应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):

enter image description here

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

占位符的作用

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

body.selectAll("div")


我们正在选择存在的div。因此,我们的回车选择将只有5个没有匹配元素的原点。例如,in this jsfiddle,HTML中已经有一个div(“这是我的图表”),结果如下:

enter image description here

我们不再看到值“ 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个元素:

enter image description here

这是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/

相关文章:

javascript - 如何使用 iconify vue 组合 API

javascript - 消失的转变

javascript - 对源自自定义属性和 td 中文本的表行进行排序

javascript - 如何正确地将数组推送到另一个数组?

javascript - 可以在菜单周围单击菜单元素

javascript - Ajax 表单未从 php 文件获取回复

javascript - 基于文本框值的 CSS 选择器

javascript - 如何减少 jquery 中按钮的事件监听器数量?

jquery - 在另一个元素的子元素之后插入一个元素

HTML5 Canvas 填充文本边距