D3 – Data-Driven Documents – Conclusion:



D3 – Data-Driven Documents – Conclusion:

0 0


d3training

Training focusing on D3 basics

On Github mspencer53 / d3training

D3

Data-Driven Documents

Or How We Learned to Stop Worrying and Love the Gantt

Conclusion:

What is D3?

  • It's awesome
  • It's fast
  • It's for data
  • It checks if your computer's fan works
https://github.com/mbostock/d3/wiki/Gallery

Paraphrase from d3js.org: D3 is a JavaScript library for manipulating documents based on data. For example, you can use D3 to generate an HTML table from an array of numbers. D3 has minimal overhead so its vary fast. It supporting large datasets and dynamic behaviors for interaction and animation. I don't want to waste your time. But if you get bored there's a Tetris demo in there you can play.

Chaining

d3.select('body')
	.append('p')
	.text('New paragraph!');
						

=

var body = d3.select('body');
var p = body.append('p');
p.text('New paragraph!');
						
First things first: Chaining & select and append.

Select

d3.select('p')
	.text('Danger Zone');
						
d3.select('#divId')
    .style('width', '200px');
						

SelectAll

d3.selectAll('p')
    .text('Danger Zone');
							
d3.select('p') is similar document.getElementsByTagName("p"); You can select tags and ids and classes and change properties.

Append

d3.select('body')
	.append('p')
	.text('This is just... babytown frolics');
						
d3.select('#divId')
	.append('p')
	.text('This is like taking candy from... a candy hating baby');
						
So with this in mind lets do something more interesting.

SVG ELEMENTS

HTML


						

D3

var canvas = d3.select('body')
	.append('svg')
	.attr('width', 500)
	.attr('height', 200);

var rect = canvas.append('rect')
	.attr('x', 10)
	.attr('y', 10)
	.attr('width', 100)
	.attr('height', 100);
							

Lets actually do something useful!

Quick make us a canvas!

var canvas = d3.select('body')
	.append('svg')
	.attr('width', 500)
	.attr('height', 200);
						

Put some bars on that Canvas!

var data = [ 250, 300, 50, 150, 100 ];

var bars = canvas.selectAll('rect')
	.data(data)
	.enter()
						

.selectAll() + .data() + .enter() = ENTER SET

Everything after this is in "for each mode"

.append('rect')
						
.attr('height', 30)
						
.attr('width', function(d){
	return d;
})
						
.attr('y', function(d,i){
	return i * 35;
});
					

Enter, Exit, Update

ENTER SET

DOM elements < data elements

canvas.selectAll('rect')
	.data(data)
	.enter()
						

Pop Quiz: How many elements will be in the Enter Set?

var canvas = d3.select('body')
	.append('svg')
	.attr('width', 500)
	.attr('height', 200);

var rect = canvas.append('rect')
	.attr('width', 100)
	.attr('height', 100);

var data = [ 250, 300, 50, 150, 100 ];

var bars = canvas.selectAll('rect')
	.data(data)
	.enter()
							

EXIT SET

DOM elements > data elements

canvas.selectAll('rect')
	.data(data)
	.exit()
						

UPDATE SET

DOM elements = data elements

canvas.selectAll('rect')
	.data(data)
						

Quick Review

If elements in our update set are changing width, we must tell them to recalculate.

canvas.selectAll('rect')
	.data(data)
	.attr('width', function(d){
		return d;
});
						

To remove elements in the exit set use .remove()

canvas.selectAll('rect')
	.data(data)
	.exit()
	.remove();
						

Transitions, Scales, Transforms & the axis of evil

Transitions

Required

Call transition:
.transition()
							
What to transition to:
.attr('fill', 'blue')
.attr('width', function(d){
	return d.width;
})
.attr('x', function(d){
	return d.x;
}))
							
A state from which to transition:
.attr('fill', 'green')
							

Transitions

Optional

.transition()
    .duration(2000)
						
.delay(1000)
						
.ease('linear')
						

Scales

Hey this is unrealistic data! o_O

data = [200, 100, 400, 300];
						
But its conveinent for drawing :)

Slightly More Realistic Data! ヽ(•‿•)ノ

data = [2.855, 0.576412, 5.188, 6.553];
							
But sucks for for drawing :(

Scales

Lets solve this with a scale function!

var widthScale = d3.scale.linear()
                   .domain([0, 6.553]) // Min to max of data
                   .range([0, 500]);    // Min to max of DOM elements
      					

...and call it when we calculate width! Brilliant!

.attr('width', function(d) { return widthScale(d); })
							

Scales

That was good, but this is better:

var widthScale = d3.scale.linear()
                   .domain([0, d3.max(data)]) // There's also d3.min(data)
                   .range([0, 500])
                   .nice();                   // Gives us some padding
      					

Transforms

.attr('transform', 'translate(10, 50)') //Move 10x and 50y
      					
.attr('transform', 'scale(1.5)') //Make things 1.5x bigger
      					
.attr('transform', 'rotate(90)') //Rotate 90 deg
      					

Or put them all together

.attr('transform', 'translate(10, 50)scale(1.5)rotate(90)')
      						

Basic Axis of Evil

var axis = d3.svg.axis()
             .scale(widthScale);
      					
canvas.call(axis);
      					

Better Axis of Evil

var axis = d3.svg.axis()
             .ticks(5)             //Default is 10
             .scale(widthScale);
      					
canvas.append('g')
      .attr('transform', 'translate(0,175)')
      .call(axis);
      					

Keying / Object Constancy

Now that you're awake we can continue...

Object Constancy

What kind of changes appear to happen in this chart?

How about this one?

Object Constancy

“Above all, animation should be meaningful. While it may be visually impressive for bars to fly around the screen during transitions, animation should only be used when it enhances understanding.“ - Mike Bostock

Key Function

var data = [
	{id:1, value:15},
	{id:2, value:20},
	{id:3, value:35}
	];

function key(d) {
  return d.id;	//can be anything as long as its unique.
}
						
canvas.selectAll('rect')
      .data(data, key)
						

Or we can do it all inline:

canvas.selectAll('rect')
      .data(data, function(d){ return d.id; })
							

Conclusion:

I love D3!!!!!!