Introduction

D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.

SVG

SVG is a text-based image format. Each SVG image is defined using markup code similar to HTML, and SVG code can be included directly within any HTML document, or inserted dynamically into the DOM. Every current web browser supports SVG. SVG is XML-based, so you’ll notice that elements that don’t have a closing tag must be self-closing. For example:

<element></element><!-- Uses closing tag -->
<element/><!-- Self-closing tag -->

Before you can draw anything, you must create an SVG element. Think of the SVG element as a canvas on which your visuals are rendered. (In that respect, SVG is conceptually similar to HTML’s canvas element. D3 can also render to an HTML canvas,but this book addresses only SVG, the most common visual output for D3.) At a minimum, it’s good to specify width and height values. If you don’t specify these, the SVG will behave like a typically greedy, block-level HTML element and take up as much room as it can within its enclosing element:

<svg width="500" height="50">
</svg>

Note that pixels are the default measurement units, so we can specify dimensions of 500 and 50, not 500px and 50px. We could have specified px explicitly, or any number of other supported units, including em, pt, in, cm, and mm.

Selections

Selections allow powerful data-driven transformation of the document object model (DOM): set attributes, styles, properties, HTML or text content, and more. Using the data join’s enter and exit selections, you can also add or remove elements to correspond to data.

Selection methods typically return the current selection, or a new selection, allowing the concise application of multiple operations on a given selection via method chaining. For example, to set the class and color style of all paragraph elements in the current document:

d3.selectAll("p")
.attr("class", "graf")
.style("color", "red");

This is equivalent to:

const p = d3.selectAll("p");
p.attr("class", "graf");
p.style("color", "red");

By convention, selection methods that return the current selection use four spaces of indent, while methods that return a new selection use only two. This helps reveal changes of context by making them stick out of the chain:

d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 500)
.append("g")
.attr("transform", "translate(20,20)")
.append("rect")
.attr("width", 920)
.attr("height", 460);

Selections are immutable. All selection methods that affect which elements are selected (or their order) return a new selection rather than modifying the current selection. However, note that elements are necessarily mutable, as selections drive transformations of the document!

Scales

Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation. Although most often used for position-encoding quantitative data, such as mapping a measurement in meters to a position in pixels for dots in a scatterplot, scales can represent virtually any visual encoding, such as diverging colors, stroke widths, or symbol size. Scales can also be used with virtually any type of data, such as named categorical data or discrete data that requires sensible breaks.

For continuous quantitative data, you typically want a linear scale. (For time series data, a time scale.) If the distribution calls for it, consider transforming data using a power or log scale. A quantize scale may aid differentiation by rounding continuous data to a fixed set of discrete values; similarly, a quantile scale computes quantiles from a sample population, and a threshold scale allows you to specify arbitrary breaks in continuous data.

For discrete ordinal (ordered) or categorical (unordered) data, an ordinal scale specifies an explicit mapping from a set of data values to a corresponding set of visual attributes (such as colors). The related band and point scales are useful for position-encoding ordinal data, such as bars in a bar chart or dots in an categorical scatterplot.

This repository does not provide color schemes; see d3-scale-chromatic for color schemes designed to work with d3-scale.

Scales have no intrinsic visual representation. However, most scales can generate and format ticks for reference marks to aid in the construction of axes.

Axes

The axis component renders human-readable reference marks for scales. This alleviates one of the more tedious tasks in visualizing data.

Regardless of orientation, axes are always rendered at the origin. To change the position of the axis with respect to the chart, specify a transform attribute on the containing element. For example:

d3.select("body").append("svg")
.attr("width", 1440)
.attr("height", 30)
.append("g")
.attr("transform", "translate(0,30)")
.call(axis);

The elements created by the axis are considered part of its public API. You can apply external stylesheets or modify the generated axis elements to customize the axis appearance.

An axis consists of a path element of class “domain” representing the extent of the scale’s domain, followed by transformed g elements of class “tick” representing each of the scale’s ticks. Each tick has a line element to draw the tick line, and a text element for the tick label. For example, here is a typical bottom-oriented axis:

<g fill="none" font-size="10" font-family="sans-serif" text-anchor="middle">
<path class="domain" stroke="currentColor" d="M0.5,6V0.5H880.5V6"></path>
<g class="tick" opacity="1" transform="translate(0.5,0)">
<line stroke="currentColor" y2="6"></line >
<text fill="currentColor" y="9" dy="0.71em" >0.0 </text>
</g>
<g class="tick" opacity="1" transform="translate(176.5,0)">
<line stroke="currentColor" y2="6"></line>
<text fill="currentColor" y="9" dy="0.71em">0.2</text>
</g>
<g class="tick" opacity="1" transform="translate(352.5,0)">
<line stroke="currentColor" y2="6"></line>
<text fill="currentColor" y="9" dy="0.71em">0.4</text>
</g>
<g class="tick" opacity="1" transform="translate(528.5,0)">
<line stroke="currentColor" y2="6"></line>
<text fill="currentColor" y="9" dy="0.71em">0.6</text>
</g>
<g class="tick" opacity="1" transform="translate(704.5,0)">
<line stroke="currentColor" y2="6"></line>
<text fill="currentColor" y="9" dy="0.71em">0.8</text>
</g>
<g class="tick" opacity="1" transform="translate(880.5,0)">
<line stroke="currentColor" y2="6"></line>
<text fill="currentColor" y="9" dy="0.71em">1.0</text>
</g>
</g>
Arrays

Data in JavaScript is often represented by an iterable (such as an array, set or generator), and so iterable manipulation is a common task when analyzing or visualizing data. For example, you might take a contiguous slice (subset) of an array, filter an array using a predicate function, or map an array to a parallel set of values using a transform function. Before looking at the methods that d3-array provides, familiarize yourself with the powerful array methods built-in to JavaScript.

JavaScript includes mutation methods that modify the array:

  • array.pop - Remove the last element from the array.
  • array.push - Add one or more elements to the end of the array.
  • array.reverse - Reverse the order of the elements of the array.
  • array.shift - Remove the first element from the array.
  • array.sort - Sort the elements of the array.
  • array.splice - Add or remove elements from the array.
  • array.unshift - Add one or more elements to the front of the array.

There are also access methods that return some representation of the array:

  • array.concat - Join the array with other array(s) or value(s).
  • array.join - Join all elements of the array into a string.
  • array.slice - Extract a section of the array.
  • array.indexOf - Find the first occurrence of a value within the array.
  • array.lastIndexOf - Find the last occurrence of a value within the array.

And finally iteration methods that apply functions to elements in the array:

  • array.filter - Create a new array with only the elements for which a predicate is true.
  • array.forEach - Call a function for each element in the array.
  • array.every - See if every element in the array satisfies a predicate.
  • array.map - Create a new array with the result of calling a function on every element in the array.
  • array.some - See if at least one element in the array satisfies a predicate.
  • array.reduce - Apply a function to reduce the array to a single value (from left-to-right).
  • array.reduceRight - Apply a function to reduce the array to a single value (from right-to-left).
Time Intervals

When visualizing time series data, analyzing temporal patterns, or working with time in general, the irregularities of conventional time units quickly become apparent. In the Gregorian calendar, for example, most months have 31 days but some have 28, 29 or 30; most years have 365 days but leap years have 366; and with daylight saving, most days have 24 hours but some have 23 or 25. Adding to complexity, daylight saving conventions vary around the world.

As a result of these temporal peculiarities, it can be difficult to perform seemingly-trivial tasks. For example, if you want to compute the number of days that have passed between two dates, you can’t simply subtract and divide by 24 hours (86,400,000 ms):

var start = new Date(2015, 02, 01), // Sun Mar 01 2015 00:00:00 GMT-0800 (PST)
end = new Date(2015, 03, 01); // Wed Apr 01 2015 00:00:00 GMT-0700 (PDT)
(end - start) / 864e5; // 30.958333333333332, oops!

You can, however, use d3.timeDay.count:

d3.timeDay.count(start, end); // 31

The day interval is one of several provided by d3-time. Each interval represents a conventional unit of time—hours, weeks, months, etc.—and has methods to calculate boundary dates. For example, d3.timeDay computes midnight (typically 12:00 AM local time) of the corresponding day. In addition to rounding and counting, intervals can also be used to generate arrays of boundary dates. For example, to compute each Sunday in the current month:

var now = new Date;
d3.timeWeek.range(d3.timeMonth.floor(now), d3.timeMonth.ceil(now));
// [Sun Jun 07 2015 00:00:00 GMT-0700 (PDT),
// Sun Jun 14 2015 00:00:00 GMT-0700 (PDT),
// Sun Jun 21 2015 00:00:00 GMT-0700 (PDT),
// Sun Jun 28 2015 00:00:00 GMT-0700 (PDT)]

The d3-time module does not implement its own calendaring system; it merely implements a convenient API for calendar math on top of ECMAScript Date. Thus, it ignores leap seconds and can only work with the local time zone and Coordinated Universal Time (UTC).

This module is used by D3’s time scales to generate sensible ticks, by D3’s time format, and can also be used directly to do things like calendar layouts.

Colors

Even though your browser understands a lot about colors, it doesn’t offer much help in manipulating colors through JavaScript. The d3-color module therefore provides representations for various color spaces, allowing specification, conversion and manipulation. (Also see d3-interpolate for color interpolation.)

For example, take the color named “steelblue”:

var c = d3.color("steelblue"); // {r: 70, g: 130, b: 180, opacity: 1}

Let’s try converting it to HSL:

var c = d3.hsl("steelblue"); // {h: 207.27…, s: 0.44, l: 0.4902…, opacity: 1}

Now rotate the hue by 90°, bump up the saturation, and format as a string for CSS:

c.h += 90;
c.s += 0.2;
c + ""; // rgb(198, 45, 205)

To fade the color slightly:

c.opacity = 0.8;
c + ""; // rgba(198, 45, 205, 0.8)

In addition to the ubiquitous and machine-friendly RGB and HSL color space, d3-color supports color spaces that are designed for humans:

CIELAB (a.k.a. “Lab”)
CIELChab (a.k.a. “LCh” or “HCL”)
Dave Green’s Cubehelix

Cubehelix features monotonic lightness, while CIELAB and its polar form CIELChab are perceptually uniform.

Paths

Say you have some code that draws to a 2D canvas:

function drawCircle(context, radius) {
context.moveTo(radius, 0);
context.arc(0, 0, radius, 0, 2 * Math.PI); }

The d3-path module lets you take this exact code and additionally render to SVG. It works by serializing CanvasPathMethods calls to SVG path data. For example:

var context = d3.path();
drawCircle(context, 40);
pathElement.setAttribute("d", context.toString());

Now code you write once can be used with both Canvas (for performance) and SVG (for convenience). For a practical example, see d3-shape.

DSV

This module provides a parser and formatter for delimiter-separated values, most commonly comma- (CSV) or tab-separated values (TSV). These tabular formats are popular with spreadsheet programs such as Microsoft Excel, and are often more space-efficient than JSON. This implementation is based on RFC 4180.

Comma (CSV) and tab (TSV) delimiters are built-in. For example, to parse:

d3.csvParse("foo,bar\n1,2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
d3.tsvParse("foo\tbar\n1\t2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]

Or to format:

d3.csvFormat([{foo: "1", bar: "2"}]); // "foo,bar\n1,2"
d3.tsvFormat([{foo: "1", bar: "2"}]); // "foo\tbar\n1\t2"

To use a different delimiter, such as “|” for pipe-separated values, use d3.dsvFormat:

var psv = d3.dsvFormat("|");
console.log(psv.parse("foo|bar\n1|2")); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]

For easy loading of DSV files in a browser, see d3-fetch’s d3.csv and d3.tsv methods.

Transitions

A transition is a selection-like interface for animating changes to the DOM. Instead of applying changes instantaneously, transitions smoothly interpolate the DOM from its current state to the desired target state over a given duration.

To apply a transition, select elements, call selection.transition, and then make the desired changes. For example:

d3.select("body")
.transition()
.style("background-color", "red");

Transitions support most selection methods (such as transition.attr and transition.style in place of selection.attr and selection.style), but not all methods are supported; for example, you must append elements or bind data before a transition starts. A transition.remove operator is provided for convenient removal of elements when the transition ends.

To compute intermediate state, transitions leverage a variety of built-in interpolators. Colors, numbers, and transforms are automatically detected. Strings with embedded numbers are also detected, as is common with many styles (such as padding or font sizes) and paths. To specify a custom interpolator, use transition.attrTween, transition.styleTween or transition.tween.