Glen
Glen

Reputation: 437

How do I correctly give a function as a parameter in JavaScript with d3

Why does the following work:

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()))

But if I directly integrate the function without declaring it first like this it doesn't work (It doesn't draw the line). Why is that? What do I have to change for it to work?

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 });
                }
            );

Upvotes: 0

Views: 577

Answers (1)

Dan
Dan

Reputation: 1591

The code

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

is creating a line generator. A line generator is a function. If you call this function and pass it your data array, then it returns the a string for the "d" attribute of an SVG path, which defines the shape of the line.

The line generator needs to know how to get the x and y coordinates for a given element in your data array. This is defined by the functions that you pass to line.x() and line.y(). These functions get called individually for each element in your data array.

In your code, function(d) { return d.x; } and function(d) { return d.y; } will be called on each element in the data array in order to get the x and y coordinates for that element. The argument to these functions, d, is a single element from your data array. It is not the entire data array.

If you don't want to define the line generator in a separate variable, then you could do the following:

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())
    );

This replaces line in your first block of code with the entire line generator.


Your code doesn't work for two reasons. First, your line generator is

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

The functions that you are passing to x() and y() do not work correctly. These functions should define how to get the x and y coordinates for a single element in your data array, like function(d) { return d.x; }. The argument, d, is one element from your data array.

Second, in the code that you have, the line generator is never called on your data array. You don't need to put the line generator inside of another function, but if you did then it would look like this:

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

But there's no need for this outer function. You can just do what I showed above.

Upvotes: 4

Related Questions