将函数传递给.attr('d')?

时间:2018-03-27 18:58:48

标签: javascript d3.js

我试图在一个.data()选择中使用两个不同的区域生成器,这样一组点可以有一个从上到下渲染的区域,而第二个区域的区域可以从左到右渲染。我可以将胖箭头函数传递给除“d”之外的每个.attr(),这会产生以下错误:

Error: <path> attribute d: Expected moveto path command ('M' or 'm'), "function area(da…".

我需要访问选择索引才能从布尔数组中设置区域。 Please see the jsfiddle I've set up with the relevant code.我评论过两次尝试将函数传递给.attr('d')

2 个答案:

答案 0 :(得分:0)

如果您检查生成的代码,您会看到:

enter image description here

所以,你没有提出价值观。而是调用函数。

(d)添加到返回值,以便执行区域生成器功能:

  .attr('d', function(d, i){
    if (horizontalNotVertical[i]) {
        return horizontalArea(d);
    } else {
        return verticalArea(d);
    }
  })

答案 1 :(得分:0)

您的代码中的问题只是D3中着名的第一个参数

您的comment

  

我想知道为什么D3会自动执行区域生成器(.attr('d', myArea)),但如果区域生成器由匿名函数返回则不会自动执行...

不正确。 D3在执行函数返回的函数时没有问题。

当你这样做......

.attr('d', myArea)

...数据自动作为第一个参数传递给myArea。我们来看一个基本演示:

var data = ["foo", "bar", "baz"];
var sel = d3.select("body").selectAll(null)
  .data(data)
  .enter()
  .append("whatever")

sel.attr("whatever", callback)

function callback(d) {
  console.log("The datum is " + d)
}
<script src="https://d3js.org/d3.v5.min.js"></script>

因此,如果要将myArea函数放在匿名函数中,则必须指定第一个参数,因为该数据传递给外部函数,而不是myArea

.attr('d', function(d){
//1st arg here------^
    myArea(d);
//and here-^
});

让我们看看:

var data = ["foo", "bar", "baz"];
var sel = d3.select("body").selectAll(null)
  .data(data)
  .enter()
  .append("whatever")

sel.attr("whatever", function(d) {
  callback(d);
})

function callback(d) {
  console.log("The datum is " + d)
}
<script src="https://d3js.org/d3.v5.min.js"></script>

因此,在您的情况下,您只需要:

.attr('d', (d, i) => (horizontalNotVertical[i]) ? horizontalArea(d) : verticalArea(d));

只是为了表明D3在执行另一个函数返回的函数时没有问题,请看看最后一个片段:

var data = ["foo", "bar", "baz"];
var sel = d3.select("body").selectAll(null)
  .data(data)
  .enter()
  .append("whatever")

sel.attr("whatever", function() {
  callback();
})

function callback() {
  console.log("I don't have the datum!")
}
<script src="https://d3js.org/d3.v5.min.js"></script>

以下是更新的jsfiddle:https://jsfiddle.net/zt5vxbm6/