Application building with D3

John Firebaugh

  • MapBox
  • jfire
  • jfirebaugh
11,728sloc
6,379sloc tests
36,010users
1,728closed issues
41translations
3lead developers
1designer

Typical Web Application

Hipster Web Application

iD

D3

jQueryD3
Ajax
Attributes
CSS
Data
Dimensions
Effects
Events
Manipulation
Selectors
Traversal
Data Binding

Declarative > Imperative

Promote the important; demote the unimportant

jQuery


$('.layers li').each(function() {
    var li = $(this);
    if (layerVisible(li.data('layer-id'))) {
        li.addClass('visible');
    } else {
        li.removeClass('visible');
    }
});
  

D3


items.classed('visible', function(layer) { return layer.visible; });
  
Raw DOM APIs jQuery D3 XSL Ember Angular
Imperative Declarative

Model-View-*Whatever

Frameworks encourage separation of business logic from presentation

Model ⇒ View Change

  • Backbone: up to you
  • Ember/Angular: smart templates

Master the Trinity

  1. Enter
  2. Update
  3. Exit

Work-minimization Techniques

  • Declare static properties on the enter selection
  • Declare dynamic properties on the update selection
  • Batch updates: no individual "instance changed" events
  • Filter the selection to the entities which actually changed

Model ⇐ View Change

Templates

Discontinuity of Expressiveness

image/svg+xml Sophistication Effort Required

Continuity of Expressiveness

image/svg+xml Sophistication Effort Required

Problem: D3 is too big!

Solution: SMASH!

mbostock/smash


D3_FILES = \
	node_modules/d3/src/start.js \
	node_modules/d3/src/arrays/index.js \
	node_modules/d3/src/behavior/behavior.js \
	node_modules/d3/src/behavior/zoom.js \
	node_modules/d3/src/core/index.js \
	[...]
	node_modules/d3/src/end.js

js/lib/d3.v3.js: $(D3_FILES)
	node_modules/.bin/smash $(D3_FILES) > [email protected]
  

Problem: D3 is too small!

jQueryD3
Dimensions

Solution: Write Plugins!


d3.selection.prototype.dimensions = function (dimensions) {
    if (!arguments.length) {
        var node = this.node();
        return [node.offsetWidth,
                node.offsetHeight];
    }
    return this.attr({width: dimensions[0], height: dimensions[1]});
};
  

More Plugins!

  • d3/d3-plugins
  • shawnbot/d3-bootstrap

Pick technology that fits your problem domain.

Thanks!