These are Scott Murray's D3 tutorials (see originals), updated to D3 v7. A note on the updates.

Drawing SVGs

Now that we’re familiar with the basic structure of an SVG image and its elements, how can we start generating shapes from our data?

You may have noticed that all properties of SVG elements are specified as attributes. That is, they are included as property/value pairs within each element tag, like this:

Hmm, that looks strangely like HTML!

We have already used D3’s handy append() and attr() methods to create new HTML elements and set their attributes. Since SVG elements exist in the DOM, just as HTML elements do, we can use append() and attr() in exactly the same way to generate SVG images!

Create the SVG

First, we need to create the SVG element in which to place all our shapes.

That will find the body and append a new svg element just before the closing </body> tag. While that will work, I recommend:

Remember how most D3 methods return a reference to the DOM element on which they act? By creating a new variable svg, we are able to capture the reference handed back by append(). Think of svg not as a “variable” but as a “reference pointing to the SVG object that we just created.” This reference will save us a lot of code later. Instead of having to search for that SVG each time — as in"svg") — we just say svg.

Alternatively, that could all be written as one line of code:

See the demo for that code. Inspect the DOM and notice that there is, indeed, an empty SVG element.

To simplify your life, I recommend putting the width and height values into variables at the top of your code, like this (view the source):

I’ll be doing that with all future examples. By variabalizing the size values, they can be easily referenced throughout your code, as in:

Also, if you send me a petition to make “variabalize” a real word, I will gladly sign it.

Data-driven Shapes

Time to add some shapes. I’ll bring back our trusty old data set

and then use data() to iterate through each data point, creating a circle for each one:

Remember, selectAll() will return empty references to all circles (which don’t exist yet), data() binds our data to the elements we’re about to create, and join() finally adds a circle to the DOM.

To make it easy to reference all of the circles later, we can create a new variable to store references to them all:

Great, but all these circles still need positions and sizes. Be warned: The following code may blow your mind.

Row of data circles

Feast your eyes on the demo. Let’s step through the code.

Takes the reference to all circles and sets the cx attribute for each one. Our data has already been bound to the circle elements, so for each circle, the value d matches the corresponding value in our original data set (5, 10, 15, 20, or 25). Another value, i, is also automatically populated for us. i is a numeric index value of the current element. Counting starts at zero, so for our “first” circle i == 0, the second circle’s i == 1 and so on. We’re using i to push each subsequent circle over to the right, because each subsequent loop through, the value of i increases.

To make sure i is available to your custom function, you must include it as an argument in the function definition (function(d, i)). You must also include d, even if you don’t use d within your function (as in the case above).

On to the next line.

h is the height of the entire SVG, so h/2 is one-half of its height. This has the effect of aligning all circles in the vertical center.

Finally, the radius r of each circle is simply set to d, the corresponding data value.

Pretty Colors, Oooh!

Color fills and strokes are just other attributes which you can set using the same methods. Simply by appending this code

we get the following (see demo):

Colorful data circles

Of course, you can mix and match attributes and custom functions to apply any combination of properties. The trick with data visualization, of course, is choosing appropriate mappings, so the visual expression of your data is understandable and useful for the viewer.