D3.js – Data-Driven Documents – SVG



D3.js – Data-Driven Documents – SVG

1 2


NeoHack2015

NeoHack2015 D3.js visualization talk

On Github Yonet / NeoHack2015

D3.js

Data-Driven Documents

Aysegul Yonet / @AysegulYonet

Slides : bit.ly/Neohack-d3

What is D3?

It is a tool for data visualization in the browser, making use of the widely implemented Scalable Vector Graphics (SVG), JavaScript, HTML5, and Cascading Style Sheets (CSS3) standards.

What d3 is not?

Not a prototyping tool.

Then Why?

Lot's of examples

SVG

  • SVG is another HTML element, except you can't put another HTML element inside an SVG.
  • SVG does not support common HTML attributes or styles such as position, left, top, right, bottom or float.
SVG is an XML markup language for describing two-dimensional vector graphics.

Circle

<circle cx="250" cy="100" r="30" fill="#25B0B0">
</circle>

Rectangle

<rect x="200" y="50" width="100" height="100" rx="10" ry="0" fill="#25B0B0">
</rect>

Interesting fact: if a properly specified value is provided for rx but not for ry (or the opposite), then the browser will consider the missing value equal to the defined one.

Line

<line x1="10" y1="10" x2="100" y2="100" stroke="blue" stroke-width="100">
</line>

Path

<path d="
M50,100
L131,66
L259,115
L339,50
L400,98
M350,150
L100,150" fill="none" stroke="#25B0B0">
</path>
  • M - move.
  • L - line.
  • z - close path.

Text

Unless you set the style of the SVG text, it inherits font-styles from CSS.

<svg>
	<text x="100" y="100" fill="red" font-family="arial" font-size="16">
		Look at me, I am a text.
	</text>
</svg>
						

Group

Any transformations (positioning, scaling, rotating) that are applied to the group element will also be applied to each of the child elements.

<g transform="translate(100, 100)">
	<circle cx="20" cy="10" r="30" fill="#25B0B0">
	</circle>
	<circle cx="100" cy="10" r="30" fill="#25B0B0">
	</circle>
</g>

SVG styles

  • background-color = fill
  • border = stroke

How to D3

Procedure to associate data with DOM

Select a parent container and child nodes Bind array of data to child nodes Append nodes to parent container Bind events, style and animate! Large datasets can be easily bound to SVG objects using simple D3 functions to generate rich text/graphic charts and diagrams. The data can be in various formats, most commonly JSON, comma-separated values (CSV) or geoJSON.

Central Principle

The central principle of D3 design is to enable the programmer to first use a CSS-style selector to select a given set of Document Object Model (DOM) nodes, then use operators to manipulate them in a similar manner to jQuery.

Selection

jQuery

var paragraphs = $("div p");

D3

var paragraphs = d3.select("div").selectAll("p");
D3 difference: child nodes might not actually exist. Selectors in D3 are declared the same way as CSS rules. An important difference is that a D3 selector object only contains the elements that matched the selection rule when the selection was first created. The selection can be based on tag (as in the below example), class, identifier, attribute, or place in the hierarchy. Once elements are selected, one can apply operations to them. This includes getting and setting attributes, display texts, and styles. Elements may also be added and removed. This process of modifying, creating and removing HTML elements can be made dependent on data, which is the basic concept of D3.js.

Data

Bind array of data to child nodes

d3.selectAll("p")
	.data([3, 7, 21, 31, 35, 42])

JSFiddle

Enter() and Append()

d3.select("body").selectAll("p")
		.data([3, 7, 21, 31, 35, 42])
	.enter().append("p");

JSFiddle

When data is bound to a selection, each element in the data array is paired with the corresponding node in the selection. If there are fewer nodes than data, the extra data elements form the enter selection, which you can instantiate by appending to the enter selection

Exit() and Remove()

var bars = d3.select('svg').selectAll('rect').data(someData);

//if we have more data, add new rectangles for those data items
bars.enter().append('rect')

//if we have less data points, remove the rectangles that no longer have a data pairing. 
bars.exit().remove();
Using D3’s exit and remove, you can get rid of outgoing nodes that are no longer needed.
// Update…
var p = d3.select("body").selectAll("p")
	.data([3, 7, 21, 31, 35, 42]);

// Enter…
p.enter().append("p")

// Exit…
p.exit().remove();
if you forget about the enter and exit selections, you will automatically select only the elements for which there exists corresponding data. By handling these three cases separately, you specify precisely which operations run on which nodes.

Let's give it a try

Exercise: bit.ly/enter-exit-exercise

If you get stuck...Sotlution

You can operate over the nodes in a declarative way using selector methods.

  • setting attributes or styles
  • registering event listeners
  • adding, removing or sorting nodes
  • and changing HTML or text content
styles, attributes, and other properties can be specified as functions of data in D3, not just simple constants

Style

You can use data values or index in a callback to define any property.

d3.select("div").selectAll("p").style("color", function(data, i) {
	return i % 2 ? "red" : "blue";
});

JSFiddle

Transition

d3.selectAll("circle")
	.attr("r", "0");
	.transition()
	.duration(750)
	.delay(function(d, i) { return i * 10; })
	.attr("r", function(d) { return Math.sqrt(d); });

Try it for yourself

Exercise 0: Look at the example and create a transition to change the size of the circles:bit.ly/d3-transitions

Exercise 1: bit.ly/d3exercise1

In case you get stuck... Solution for Exercise 1

More Advanced D3

Scales and Domains

Axis

Loading external data

Scales

Scales transform a number in a certain interval (called the domain) into a number in another interval (called the range).

  • d3.scale.linear - construct a linear quantitative scale.
  • domain - get or set the scale's input domain.
  • range - get or set the scale's output range.

Quantitative Scale

  • Linear scales
  • Logarithmic scales
  • Power scales (including square root scales)
var x = d3.scale.linear()
		.domain([0, d3.max(data)])
		.range([0, 420]);
d3.select(".chart")
	.selectAll("div")
		.data([3, 7, 21, 31, 35, 42])
	.enter().append("div")
		.style("width", function(d) { return x(d) + "px"; })
JSFiddle

Ordinal Scale

Ordinal Scale have a discrete domain, such as a set of names or categories.

var x = d3.scale.ordinal()
	.domain(["A", "B", "C", "D", "E", "F"])
	.rangeRoundBands([0, width], .1);

Color Categories

d3.scale.category10() - Constructs a new ordinal scale with a range of ten categorical colors:

JSFiddle

Let's refactor our bar chart.

Create a bar charts with scale

Solution: Bar Charts with Scale

Axis

d3.svg.axis creates a new axis generator.

  • axis.scale
  • axis.orient
  • axis.ticks
  • axis.tickFormat
var xAxis = d3.svg.axis()
    .scale(x)
    .orient('bottom')
    .tickValues(data);
JSFiddle

d3.time

d3.time.format - creates a new local time formatter for a given specifier.

d3.time.format("%Y-%m-%d");
JSFiddle

d3.time.scale - constructs a linear time scale.

var xScale = d3.time.scale()
 .domain([2009-07-13T00:02, 2009-07-13T23:48])
 .rangeRound([0, width]);
 //rangeRound does the same thing as range but rounds the values to integers or begining of dates.
JSFiddle

d3.time.intervals - a time interval in local time.

  • d3.time.hour
  • d3.time.week
  • d3.time.monday
  • d3.time.year

Working with Arrays

Most commonly used functions

  • d3.min/d3.max
  • d3.range
  • d3.keys - lists the keys of an associative array.
  • d3.merge - merges multiple arrays into one array.
  • d3.nest - groups array elements hierarchically.

Loading External Resources

  • d3.json
  • d3.csv
  • d3.tsv
Don't forget to put the functions inside the async function.

Examples

Bar Chart with tooltip

Pie Chart

Good News!

Other D3 resources

THE END

BY Aysegul Yonet / @AysegulYonet

Slides : bit.ly/Neohack-d3