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) > $@
  

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!