【问题标题】:Passing a function to .attr('d')?将函数传递给 .attr('d')?
【发布时间】:2018-09-06 07:32:16
【问题描述】:

我试图在一个.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') 的两次尝试。

【问题讨论】:

  • 有趣的是,即使是像mySelection.attr('d', () => myArea) 这样简单的空胖箭头函数也会引发错误
  • 我正在使用 Opera,没有错误,我可以看到图表。你的浏览器是什么??
  • 它无法在 Chrome 和 Firefox 中加载(在注释第 18 行和取消注释第 19 行或第 20-26 行之后),尽管只有 Chrome 会引发错误。

标签: javascript d3.js


【解决方案1】:

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

所以,你没有得到价值。而是调用该函数。

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

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

【讨论】:

  • 这对我有用,谢谢!我想 D3 如果传递给attr('d') 只是执行一个函数是有道理的,无论该函数是一个胖箭头函数还是一个区域生成器,但我很好奇为什么 D3 不类似地执行由返回的区域生成器粗箭头函数。
  • 在这两种情况下,您都需要提供数据: .attr('d', (d, i) => (horizo​​ntalNotVertical[i]) ? Horizo​​ntalArea(d) : verticalArea(d))
  • 抱歉,我的评论不清楚。我想知道为什么 D3 会自动执行区域生成器,如果它自己传递(.attr('d', myArea))但如果区域生成器由匿名函数返回,则不会自动执行......但现在我意识到如果 D3 要执行函数返回的函数,可能会导致递归错误!
【解决方案2】:

代码中的问题只是 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 执行另一个函数返回的函数没有问题,看看最后这个 sn-p:

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/

【讨论】:

  • 在尝试回答 question 这是这个问题的 TypeScript 风格时,我认为这种类型必须有一个很好的欺骗目标(但不想关闭为重复,只是参考它)。甚至您的回答也开始谈论 着名 第一个参数,即 不要调用该函数,只需传递它的引用 ...但是,我无法找到一个不错的规范目标。你知道吗?
  • @altocumulus 可能是this one?
  • 这太笼统了。我正在寻找一款专门针对 D3 的产品。
猜你喜欢
  • 2021-09-08
  • 2019-12-15
  • 2014-05-15
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 2014-09-10
  • 2013-01-10
相关资源
最近更新 更多