Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use of "d" in function literal in D3?

I am teaching myself D3 without too much knowledge on syntax / grammar of javascript. Could anyone explain the use of "d" as a parameter in the following function literal?

I see that it points to the data set being worked on, but want to understand the grammar behind this.

    d3.selectAll("circle")
        .attr("cy",function (d) { return percent_scale(d.late_percent);})
        .attr("cx",function (d) { return time_scale(d.time);})
        .attr("r",1);
like image 442
user3562812 Avatar asked Jun 23 '14 05:06

user3562812


People also ask

What does D mean in D3?

Vitamin D3, or cholecalciferol, is one of the forms of vitamin D. Both D2 and D3 need to be converted by the liver and then by the kidneys into the main form of vitamin D that circulates in your body.

Which is or are the main selection in D3?

D3 provides two top-level methods for selecting elements: select and selectAll. These methods accept selector strings; the former selects only the first matching element, while the latter selects all matching elements in document traversal order.


1 Answers

This is called an anonymous function, which is a function that isn't given a named label. Anonymous functions in Javascript are objects like everything else and this is why you can pass them as parameters into other javascript functions.

In the case of d3, it allows you to pass in a function as the second parameter. As you discovered, this function will be called with the current data element as well as the index of the current data element. If the second parameter is not a function, it can use a value instead.

In your example:

d3.selectAll("circle")
        .attr("cy",function (d) { return percent_scale(d.late_percent);})
        .attr("cx",function (d) { return time_scale(d.time);})
        .attr("r",1);

Both cy and cx are being assigned values based on the return value of an anonymous function call, while r is being assigned a static value. We could rewrite this as:

function setY(d) { return percent_scale(d.late_percent);}

function setX(d) { return time_scale(d.time); }

d3.selectAll("circle")
        .attr("cy", setY)
        .attr("cx", setX)
        .attr("r",1);

Here I've replaced the anonymous function calls with more standard function definitions and specified the name of the function to be called in the d3 call. This works exactly the same as before. Also note that there is nothing magical about d in this case.

function setY(foo) { return percent_scale(foo.late_percent);}

function setX(foo) { return time_scale(foo.time); }

d3.selectAll("circle")
        .attr("cy", setY)
        .attr("cx", setX)
        .attr("r",1);

This code will also do the same thing. Note that I've renamed the parameter from d to foo, but this just changes how you access the parameter within the function. It has no effect outside of the function call. Generally in d3 documentation and tutorials, you'll see d used for the current data element and i used for the index of the current data element. The index is passed in as the second element to the function calls like so:

function setY(d, i) { return percent_scale(d.late_percent);}

function setX(d, i) { return time_scale(d.time); }

d3.selectAll("circle")
        .attr("cy", setY)
        .attr("cx", setX)
        .attr("r",1);

Now specifically in the d3 case:

// Select all of the 'circle' elements (that is <circle>) elements
// in the HTML document and put the associated data into an array
d3.selectAll("circle")

        // For each circle element, set the Y position to be the result
        // of calling percent_scale on the data element late_percent
        .attr("cy",function (d) { return percent_scale(d.late_percent);})

        // For each circle element, set the X position to be the result
        // of calling time_scale on the data element time
        .attr("cx",function (d) { return time_scale(d.time);})

        // For each circle element, set the radius to be 1
        .attr("r",1);

This is a very common construct in d3. The first step is always to make a selection to define which set of elements you want to modify (this is the .selectAll in this case). After that, you can chain together additional calls (in this case the .attr calls) that actually perform the desired modifications to the elements.

This creates a very powerful method of working with data driven documents (like graphs, charts, etc) without having to track the data elements manually or have to create lots of loops. In fact, you can usually tell you are using d3 incorrectly if you have any loops in your code that deals with modifying elements.

If you don't have much experience with javascript, the tutorials at https://www.dashingd3js.com/ might be helpful for getting started with d3.

like image 131
Bill Avatar answered Jan 17 '23 19:01

Bill