D3.js is something I’ve been meaning to pick up and learn for a while. In my long flight and train rides, I’ve had time to go through and play around with some of its powerful features. In this blog post, I’ll just cover the very basic concepts of D3; selectors, modification of DOM elements, and data joins.

Selectors

If you’ve used jQuery before, this is really straight forward. D3 allows you to select DOM elements using the select or selectAll functions. The difference being that the first function selects the first matching element whereas the second function will select all matching elements.

d3.select("div");
//=> selects the first div element in the document and returns a sudo-array object
d3.selectAll("div");
//=> selects all div elements in the document and returns a sudo-array object

Modifying the DOM

Also similar to jQuery, D3 allows you to modify DOM elements that have been selected. Some of the more common functions used to change the DOM is shown in the following example.

//=> first, select one or more elements and store to variable
var divs = d3.selectAll("div");

//=> next, call the modifier functions on the selection
divs.attr("hello", "world") //attr will set the div's "hello" attribute value to "world"
divs.style("background-color", "blue") //style changes the css property of the elements
divs.text("foo bar!") //text will replace the text content of the elements
divs.append("div") //append will append a new element of the given name to the end of the selection
divs.remove() //remove will remove the selected elements from the DOM

Data Joins

Here’s where the real fun begins. D3 allows you to bind data to DOM elements and use it as you need. The data can be bound using the data function and providing it an array of data. For example, let’s say that you have 3 div elements on your page. You can select all the divs using the selector and bind different data to each element like this:

var divs = d3.selectAll("div");
divs.data([1,2,3]) //data will bind each element of the provided array to the selected DOM elements

After the data is bound, it can be used as a basis for modifying the elements. This really comes in handy because D3.js is a data visualization tool so you can start to format things based on the data bound to the element. As an example, let’s use the style function from before to drive the styling of the elements from the data.

divs.style("width", function(d,i) {return (i+1) * d * 10 + "px"})
    .style("height", function(d,i) {return (i+1) * d * 10 + "px"})
    .style("background-color", "black");

In the first two lines, we specify that the width and height property be set to the return value of the function. The function automatically gets 2 arguments: the data value of the element and the index value of the element in the selected array.  The function uses those two arguments to calculate the width and length of the divs. The styles get applied to all three div elements so you can think of it as doing a loop through the array of divs.

Another powerful feature of data joins is that you can add or remove multiple elements based on the data join of the elements. Let’s say for example, that instead of 3 data points in the previous example, we have 10. Then we can simply pass in the data array to the data function and add those to the DOM.

divs.data([1,2,3,4,5,6,7,8,9,10])
    .enter()
  .append("div")
    .style("width", function(d,i) {return (i+1) * d * 10 + "px"})
    .style("height", function(d,i) {return (i+1) * d * 10 + "px"})
    .style("background-color", "black")

An important note is that the enter function is used. This function will only apply the proceeding method chain to new elements that are going to enter the DOM. In this case, the first 3 elements were already in the DOM so they will not be effected. However, the enter function will return the entering elements and they will be appended to the DOM with the specified styles.

On the other hand, if we wanted to remove elements from the DOM, we would apply the opposite function called exit and then remove those elements that are yielded from the exit function.

d3.selectAll("div")
    .data([1])
    .exit()
  .remove()

Once you get the hang of manipulating elements, you can add animations to them using transition and duration to make some cool stuff. Oh and I forgot to mention that you can use these exact same functions to modify SVG elements. Combining everything together will look something like this:

var svg = d3.select("body")
            .append("svg")
              .attr("width", 720)
              .attr("height", 720)

svg.selectAll("circle")
    .data([4, 10, 20])
    .enter()
  .append("circle")
    .attr("cx", function(d){return d * 5})
    .attr("cy", function(d){return d * 5})
    .attr("r", 10)

var circles = d3.selectAll("circle")

circles.transition()
     .duration(2000)
     .attr("cx", function(){return Math.random() * 200})
     .attr("cy", function(){return Math.random() * 200})
     .attr("r", function(){return Math.random() * 50})

Whew, that about wraps up the basic D3.js functions. There’s way more you can do with D3, but that’s it for now. Until next time, happy coding!