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");
}
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
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
d3.select('.sparkline') VS d3.selectAll('.sparkline')
It shall be named "sparklineS"