Making of a d3 plugin – Illustrated by d3 sparklines



Making of a d3 plugin – Illustrated by d3 sparklines

0 0


d3-plugin-making-of

Presented at D3js Paris meetup on March 29th 2016

On Github davinov / d3-plugin-making-of

Making of a d3 plugin

David Nowinsky @davinov - Toucan Toco

Illustrated by d3 sparklines

Everything is a module

“ Although the word plugin suggests extending core functionality, this pattern is used internally by D3 to organize the code into modules. Thus, you can use this pattern to replace default behavior or to pick a subset of features for a custom build. Another way of thinking about it is that everything in D3 is a plugin, including core features like colors, scales, and selections.”
  • d3.scale

    d3.scale.linear()
    .domain([-1, 0, 1])
    .range(["red", "white", "green"]);
    								
  • d3.svg.axis

    d3.svg.axis()
    .scale(xScale)
    .orient("bottom");
    							
  • d3.select
  • d3.layouts

When to do a module?

Oh f**k I need to do that on this too. Already done that three times!

Reusability

Factorisation

A stupid plugin

d3.stupid = {};
					
d3.stupid.sayHello = function() {
	console.log("hello");
}
					

Litterature

Sparkline theory and practice - Edward Tufte

Design

Different types of plugins

Computations

Scales Layouts

SVG Components

Shapes Axis

In components...

“You’ll find your components much easier to reuse and reason about if you divide them into two categories. I call them Container and Presentational components but I also heard Fat and Skinny, Smart and Dumb, Stateful and Pure, Screens and Components, etc.These all are not exactly the same, but the core idea is similar.”

(In React's world)

Compuationals

Scales Layouts

Presentationals

Shapes Axis

Containers

? See d3 plugins repository Our charts?

Container means it manages a state

Sparklines' component type?

See the Pen d3 sparklines by David Nowinsky (@davinov) on CodePen.

Presentation

with a tiny state ;)

I/O s

What do we need (for presentational components)?

A d3 selection

d3.stupid.writeHello = function(d3Selection) {
	d3Selection
	.text('Hello!');
};
						
d3.toucan.sparklines = function(d3Selection) {
	d3Selection
	.enter()
	.append('path');

	d3Selection
	.exit()
	.remove();

	d3Selection
	.select('path')
	.attr('d', function(d) {
		...
	});
};
						

Customisability

Towards reusable charts

“I’d like to propose a convention for encapsulating reusable charts in D3.”
function chart() {
	// generate chart here
}
				
From...
d3.stupid.writeHello = function(d3Selection) {
	d3Selection
	.text('Hello!');
};
				
To...
d3.stupid.writeHello = function(options) {

	helloWriter = function(d3Selection) {
		d3Selection
		.text('Hello!');

		// Use options here!
	};

	return helloWriter;
};
				
  • Private options
  • Default values
  • Reconfiguration
d3.stupid.writeHello = function(options) {

	helloWriter = function(d3Selection) {
		d3Selection
		.text('Hello!');
	};

	return helloWriter;
};
				
  • dateSelector
  • valueSelector
  • width
  • height
  • transitionDuration
  • unit
  • dateFormat: optional formatting of dates in tooltip
  • valueFormat: optional formatting of values in tooltip
  • forceLexicalOrder: optional, default true, set to false to force lexical reordering of ordinal dates
  • commonScatter: false by default, use the same scatter for all sparklines (y axis)
  • selectionTimeout: default 2000, time before tooltip disappears, 0 to disable
  • tooltipYOffset: default 0, offset of the tooltip

Composabilty

Breaking into smaller(st) components?

Little big details

A while ago...

d3.select('.sparkline') VS d3.selectAll('.sparkline')

It shall be named "sparklineS"

Best pratices

Have fun extending d3!

@davinov - Toucan Toco toucantoco.com/sparklines