The world’s leading publication for data science, AI, and ML professionals.

Introduction to Data-Driven Shapes in D3.js

Using the Fibonacci Sequence

Photo by Ira Mint on Unsplash
Photo by Ira Mint on Unsplash

As a devout python fan, I’ve regrettably shied away from exploring many Data Visualization tools that are beyond the scope of libraries like Matplotlib, Seaborn, and Plotly. While perusing the diverse capabilities of D3.js in this visualization gallery, however, I was definitely excited to dip my toes in the water.

D3 is a JavaScript library that supports highly customizable and interactive web-based data visualizations. It’s short for "Data Driven Documents," and it allows developers to create and manipulate web documents based on data. Having some prior familiarity with HTML, CSS and JavaScript will make it easier to get started with D3, but making simple shapes is possible with just the bare basics. This article will introduce some common shapes in D3 – including rectangles, circles, ellipses, lines and text – whose size will be based on numbers in the Fibonacci Sequence. These are just a sample of the many types of shapes that can be easily generated with D3 code.

What You’ll Need

To start making visualizations in D3, you will need a text editor, such as Atom, to edit your code. You’ll also want to copy the contents of the latest version of D3.js and paste them into a .js file in your text editor. In addition to the D3 file, you’ll need the following:

  • An HTML file to reference CSS and JavaScript documents and format the structure of the webpage
  • A CSS file to format the webpage’s contents
  • A JavaScript file for your D3 code

We’ll now take a closer look at the contents of each of these files.

The HTML File

The HTML file allows you to render visualizations that you create in D3 in your browser. The HTML code we’ll use is pretty bare-bones:

The first line declares that this is an HTML document, and the second line specifies that the document’s contents will be in the English language. The head tags mark the document’s head element, which contains its meta data. The text within the title tags is rendered in a browser tab when you open the HTML document in a browser.

The next two lines inside the head tags reference the CSS file and the contents of version 6 of D3, respectively. If you choose to use different names for the files you’re referencing, the names will need to be updated in these lines. The same goes for the ‘shapes.js’ file referenced within the document’s body, which contains all of its visible contents. Finally, the closing html tag marks the end of the document.

The CSS File

CSS is a style sheet language that handles such features as colors, fonts, and spacing in a webpage. In this simple file, we set the margin of the page to zero pixels (no white space around the elements) and the height to 100% (larger elements will fill the page, but not go outside of its bounds to render scrollbars):

The JavaScript File

The ‘shapes.js’ file is where we’ll put the D3 code to create shapes based on the Fibonacci Sequence. This sequence of numbers starts with 0 and 1, and each following number is the sum of the two numbers before it. Below, we define a variable, ‘dataArray’ that contains the data the shapes will be based on:

We’ll also create an ‘svg’ variable with the following code:

SVG stands for ‘scaleable vector graphics,’ and this svg element can be thought of as a blank canvas for D3 shapes. We select the body section of the HTML document, and append (i.e., add) an svg element to it. The height and width attributes are both set to 100% so that shapes appended to this element will fill the entire page.

Rectangles

Next, we’ll append some rectangles:

Here, we select all rectangles that will be appended to the svg element, and the subsequent attributes control their dimensions, color, and position on the page. Chaining .data(dataArray) to the selection binds our Fibonacci data to the rectangles. Notice that the rectangles have a static width of 50 pixels, but that their height is dynamic:

Image by author
Image by author

That’s because the height is based on a function that uses the ‘dataArray’ bound to the selection. The ‘d’ and ‘i’ in the function definition represent individual data points and their position (index) in the array, respectively. You may give these parameters any name you’d like and the function will still have the same output.

The function runs through the data array in order. In the shortest, leftmost rectangle you see above, the height is 1*15 or 15 pixels. The second rectangle is also 15 pixels high, the third rectangle is 30 pixels, and so on. The data array is also used to dynamically change the ‘x’ and ‘y’ attributes such that the rectangles are centered vertically and evenly spaced horizontally. You can change the values within these attributes’ functions to observe how the rectangles’ position changes.

Circles

Next, we’ll add some circles to the page:

We start by defining a new variable, ‘newX,’ for later use in the function that sets the horizontal position of the circles. Notice that we select all ‘circle.first’ elements on the page. We’ve assigned ‘first’ to the circles’ ‘class’ attribute because we’re going to add multiple sets of circles to the page. Creating classes and specifying elements of a particular class eliminates any confusion about which shapes you intend to select. The circles’ radius is determined by the ‘r’ attribute and is the product of 3 and each data point in the array.

We’ll now add a second set of circles:

Notice that in the image below, the silver circles are spaced closer together than the purple circles, the initial circles in the sequence have a slightly smaller radius, and they have a lower vertical position on the page. These differences are determined by the separate values (both static and dynamic) that have been assigned to attributes of the ‘first’ and ‘second’ class of circles:

Image by author
Image by author

Ellipses

Ellipses are similar to circles, but instead of having a single ‘r’ attribute, they have both an ‘rx’ and ‘ry’ attribute:

These attributes allow you to separately adjust the horizontal and vertical radii of the ellipses. The ellipses below have a static vertical radius of 50 pixels and a dynamic horizontal radius that is three times their corresponding value in the data array:

Image by author
Image by author

It may appear that the vertical radii are decreasing at later points in the sequence, despite being assigned a static value. The steady increase in the horizontal radii create this appearance as the x:y ratio changes.

Lines

Let’s now take a look at some code for adding lines:

Here is what each of the new attributes refer to in the below image:

  • x1: the horizontal position of the right end of the line
  • x2: the horizontal position of the left end of the line
  • y1: the vertical position of the right end of the line
  • y2: the vertical position of the left end of the line
  • stroke: the color of the line
  • stroke-width: the width of the line
Image by author
Image by author

Since x2 and y2 are static, you’ll notice that all of the lines originate from a single point, but that their length and position from there changes according to the Fibonacci values they have been assigned.

Text

Finally, let’s add some text!

Stroke and stroke width, as with other shapes, refer to the outline color and width for the shape. The ‘text-anchor’ attribute allows you to adjust the text alignment, which here is the start, or left side, of the page. The ‘.text’ line adds each data point in the data array to the text. Below, this code has been reused to include multiple lines of the Fibonacci numbers in different colors and different y positions on the page:

Image by author
Image by author

Conclusion

The Fibonacci sequence isn’t meaningful data, but it’s useful for illustrating how the size, spacing, and other attributes of D3 shapes can be dynamically updated based on data in an array. This article has not even scratched the surface of all that’s possible with shapes in D3, but I hope it encourages other beginners to join me in exploring this powerful visualization library!


Related Articles