首页 > 解决方案 > 如何使用 d3 在 JavaScript 中正确地将函数作为参数提供

问题描述

为什么以下工作:

var line = d3.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });
var path = d3.select("#frame")
            .append("path")
            .attr("class", "line")
            .attr("d", line(nodes.data()))

但是,如果我直接集成该函数而不像这样首先声明它,它就不起作用(它不画线)。这是为什么?我必须改变什么才能让它工作?

var path = d3.select("#frame")
            .append("path")
            .attr("class", "line")
            .attr(
                "d", 
                function() {
                    d3.line()
                        .x(function() { return nodes.data().x })
                        .y(function() { return nodes.data().y });
                }
            );

标签: javascriptd3.js

解决方案


编码

var line = d3.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

正在创建一个线生成器。线生成器是一个函数。如果您调用此函数并将您的数据数组传递给它,那么它会返回 SVG 路径的“d”属性的字符串,它定义了线条的形状。

线生成器需要知道如何获取数据数组中给定元素的 x 和 y 坐标。line.x()这是由您传递给和的函数定义的line.y()。这些函数会为数据数组中的每个元素单独调用。

在您的代码中,function(d) { return d.x; }function(d) { return d.y; }在数据数组中的每个元素上调用,以获取该元素的 x 和 y 坐标。这些函数的参数d, 是数据数组中的单个元素。它不是整个数据数组。

如果您不想在单独的变量中定义行生成器,则可以执行以下操作:

var path = d3.select("#frame")
  .append("path")
    .attr("class", "line")
    .attr("d", d3.line()
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })(nodes.data())
    );

这将line在您的第一个代码块中替换为整个行生成器。


您的代码不起作用有两个原因。首先,您的线路发生器是

d3.line()
    .x(function() { return nodes.data().x })
    .y(function() { return nodes.data().y })

您传递给的函数x()不能y()正常工作。这些函数应该定义如何获取数据数组中单个元素的 x 和 y 坐标,例如function(d) { return d.x; }. 参数 ,d是数据数组中的一个元素。

其次,在您拥有的代码中,永远不会在您的数据数组上调用行生成器。您不需要将行生成器放在另一个函数中,但如果您这样做了,它将如下所示:

function() {
  return d3.line()
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })(nodes.data());
}

但是不需要这个外部函数。你可以做我上面展示的。


推荐阅读