如何通过自定义过滤器功能扩展d3.js选择?

时间:2019-07-17 12:32:51

标签: javascript d3.js

我经常使用这种过滤功能,只是跳过空数据:

selection
    .data(array).enter()
    .filter(function(d) { return d === null ? null : this })
    .append("something")

因此,我决定简化使用 notnull 函数扩展选择范围的代码:

d3.selection.enter.prototype.notnull = function() {
    return this.filter(function(d) {
        return d === null ? null : this 
    })
}

所以我可以这样简单地编写代码:

selection
    .data(array).enter()
    .notnull()
    .append("something")

这似乎可行,但是很明显我的返回值有问题,因为出现了这个错误:

  

TypeError:selection.data(...)。enter(...)。notnull(...)。append不是函数

现在我真的很难理解为什么。有什么建议吗?

编辑

这个问题是不正确的,第一个例子必须是:

selection
    .data(array).enter()
    .append("something")
    .filter(function(d) { return d === null ? null : this })

但这会留下很多空的svg实体,因此,正如鲁本指出的那样,方法是在数据数组上使用Array.filter。

1 个答案:

答案 0 :(得分:-1)

我为您的原始过滤器代码创建了一个代码段-没有自定义功能-发现它有两件事。首先,它引发错误:Uncaught TypeError: selection.data(...).enter(...).filter(...).append is not a function,其次,它记录了调用filter的参数。

var array = [1, 2, 3, 4, null, 5, 6, 7];

var selection = d3.select('body').selectAll('span');

selection
  .data(array).enter()
  .filter(function(d) {
    console.log(d);
    return d === null ? null : this;
  })
  .append("span")
  .text(function(d) {
    return d;
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

<body>
</body>

在这里,我们看到d实际上是一个值数组,因此.filter()是在数组的数组上调用的,而不仅仅是数组本身。要解决此问题,您可以做两件事:您可以.data(array.filter(function(d) { return return d !== null; }));决定将数据传递到d3js之前进行过滤,或者为所有数据添加span标签之后可以过滤数据。下面的代码段以一种有效的方式显示了您的代码:

var array = [1, 2, 3, 4, null, 5, 6, 7];

var selection = d3.select('body').selectAll('span');

d3.selection.prototype.notnull = function() {
  return this.filter(function(d) {
    return d === null ? null : this
  })
}

selection
  .data(array).enter()
  .append("span")
  .notnull()
  .text(function(d) {
    return d;
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>