D3.js – Data-Driven Documents



D3.js – Data-Driven Documents

0 0


d3js

D3js Presentation. An introduction to D3 core concepts

On Github cminatti / d3js

D3.js

Data-Driven Documents

http://d3js.org/

Examples

http://bl.ocks.org/mbostock http://www.mftransparency.org/microfinance-pricing/

Browser Support?

Any browser that supports SVG

http://caniuse.com/#feat=svg

D3.js

Selectors

//d3.js    
d3.selectAll("p").style("color", "white");
//jQuery
$("p").css("color", "white");

D3.js

Dynamic Properties

//dynamic properties
d3.selectAll("p").style("color", function() {
  return "hsl(" + Math.random() * 360 + ",100%,50%)";
});
//jQuery
$("p").css("color", function() {
  return "hsl(" + Math.random() * 360 + ",100%,50%)";
});
test1.html

D3.js

Events

//dynamic properties
d3.selectAll("p").on("click", function(datum, index) { 
        alert("Event fired on "+this+": "+d3.event.type );
});

//jQuery
$("p").on("click", function(e) { 
        alert("Event Fired on "+this+": "+e.type ); 
});
test2.html Doc: https://github.com/mbostock/d3/wiki/Selections#on

D3.js

Dynamic Properties based on bound Data

//dynamic properties
d3.selectAll("p")
    .data([4, 8, 15, 16, 23, 42])
    .style("font-size", function(d) { return d + "px"; })
    .text(function(d) { return "This p has font size " + d + "." });
test1.html

D3 Selections

A selection is an array of elements pulled from the current document.

After selecting elements, you apply operators to them to do stuff. These operators can get or set attributes, styles, properties, HTML and text content.

You can also join selections to data; this data is available to operators for data-driven transformations. In addition, joining to data produces enter and exit subselections, so that you may add or remove elements in response to changes in data.

https://github.com/mbostock/d3/wiki/Selections

D3.js

Add Elements

d3.select("body").selectAll("p")
    .data([4, 8, 15, 16, 23, 42])
  .enter().append("p")
    .text(function(d) { return "I’m number " + d + "!"; });
test2.html

D3.js

Update, Enter & Exit

// Update…
var p = d3.select("body").selectAll("p")
    .data([4, 8, 10, 20, 30])
    .text(function(d) { return "I’m number " + d + "!"; });

// Enter…
p.enter().append("p")
    .text(function(d) { return "I’m number " + d + "! Just entered."; });

// Exit…
p.exit().remove();
test2.html
//Scatterplot data
var data = [
  {x: 10.0, y: 9.14},
  {x:  8.0, y: 8.14},
  {x: 13.0, y: 8.74},
  {x:  9.0, y: 8.77},
  {x: 11.0, y: 9.26},
  {x: 14.0, y: 8.10},
  {x:  6.0, y: 6.13},
  {x:  4.0, y: 3.10},
  {x: 12.0, y: 9.13},
  {x:  7.0, y: 7.26},
  {x:  5.0, y: 4.74},
];

Full example & Key function

var data = [
        {x: 10.0, y: 9.14},
        {x:  8.0, y: 8.14},
        {x: 13.0, y: 8.74},
        {x:  9.0, y: 8.77},
        {x: 11.0, y: 9.26},
        {x: 14.0, y: 8.10},
        {x:  6.0, y: 6.13},
        {x:  4.0, y: 3.10},
        {x: 12.0, y: 9.13},
        {x:  7.0, y: 7.26},
        {x:  5.0, y: 4.74},
      ];

    var margin = {top: 80, right: 80, bottom: 20, left: 80},
      width = 540,
      height = 380;

    //creates the X scale
    var x = d3.scale.linear()
        .domain([0, 20])
        .range([0, width - margin.left - margin.right]);
        

    //creates the Y scale
    var y = d3.scale.linear()
        .domain([0, 20])
        .range([height - margin.top - margin.bottom, 0]);

    //helper to draw X Axis
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .tickPadding(8);

    //helper to draw Y Axis
    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .tickPadding(8);

    //Append SVG
    var svg = d3.select("body").append("svg")
              .attr("width", width)
              .attr("height", height)
              .attr("class", "dot chart")
            .append("g")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
                ;

    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + y.range()[0] + ")")
        .call(xAxis);

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    //Append circles
    svg.selectAll(".dot")
              .data(data, function(d) { return d.x } ) //the data set
            .enter().append("circle")
              .attr("class", "dot")
              .attr("cx", function(d) {return x(d.x); })
              .attr("cy", function(d) {return y(d.y); })
              .attr("r", 12);

    //Update Circles
    svg.selectAll(".dot")
              .data(data) //the data set
            .transition().duration(1000).delay(200)
              .attr("class", "dot")
              .attr("cx", function(d) {return x(d.x); })
              .attr("cy", function(d) {return y(d.y); })
              .attr("r", 12);
test2.html Example taken from: http://bost.ocks.org/mike/d3/workshop/
3456789101112131415234567891011
Example taken from: http://bost.ocks.org/mike/d3/workshop/

D3.js

Transitions

For example, to fade the background of the page to black:
d3.select("body").transition()
    .style("background-color", "black");
Or, to resize circles in a symbol map with a staggered delay:
d3.selectAll("circle").transition()
    .duration(750)
    .delay(function(d, i) { return i * 10; })
    .attr("r", function(d) { return Math.sqrt(d * scale); });

D3.js

Transitions

D3 has many built-in interpolators to simplify the transitioning of arbitrary values. For instance, you can transition from the font string "500 12px sans-serif" to "300 42px sans-serif", and D3 will find the numbers embedded within the string, interpolating both font size and weight automatically.

https://github.com/mbostock/d3/wiki/Transitions http://bost.ocks.org/mike/transition/

D3.js

Your Own Interpolator

If you want to implement your own interpolator, you need a function that takes a single argument t ranging from 0 to 1. For t = 0, the interpolator returns the starting value; for t = 1, the interpolator returns the ending value; and for values in-between, the interpolator returns a blending value. For example, to interpolate two numbers:

function interpolateNumber(a, b) {
  return function(t) {
    return a + t * (b - a);
  };
}

D3.js

There is more stuff to help you

  • Log scales, power scales, quantized scales, ordinal scales ...
  • Geographic projections and country map data.
  • Drag and touch events, colour space functions, date formatting, array manipulation, ...
  • Helper functions for different charts layouts: chord, histogram, hierarchy, pie, stack, tree, cluster, pack ...

D3.js

Layouts

  • Bundle - apply Holten's hierarchical bundling algorithm to edges.
  • Chord - produce a chord diagram from a matrix of relationships.
  • Cluster - cluster entities into a dendrogram.
  • Force - position linked nodes using physical simulation.
  • Hierarchy - derive a custom hierarchical layout implementation.
  • Histogram - compute the distribution of data using quantized bins.
  • Pack - produce a hierarchical layout using recursive circle-packing.
  • Partition - recursively partition a node tree into a sunburst or icicle.
  • Pie - compute the start and end angles for arcs in a pie or donut chart.
  • Stack - compute the baseline for each series in a stacked bar or area chart.
  • Tree - position a tree of nodes tidily.
  • Treemap - use recursive spatial subdivision to display a tree of nodes.
https://github.com/mbostock/d3/wiki/Layouts

SVG

Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. The SVG specification is an open standard developed by the World Wide Web Consortium (W3C) since 1999. SVG images and their behaviors are defined in XML text files.

Resources

D3 Resources

Libraries built on top of D3.js

To build your own graph library start here:

function chart() {
  // generate chart here
}
function chart(width, height) {
  // generate chart here, using `width` and `height`
}
function chart(config) {
  // generate chart here, using `config.width` and `config.height`
}
function chart(config) {
    
    //do stuff

  return function(selection) {
    // generate chart here, using `config.width` and `config.height`
  };

}

var myChart = chart({width: 720, height: 80});

d3.selectAll("p").data(data).call(myChart); 
//or
myChart( d3.selectAll("p").data(data) );
function chart() {
  var width = 720, // default width
      height = 80; // default height

  function my(selection) {
    // generate chart here, using `width` and `height`
  }

  my.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return my;
  };

  my.height = function(value) {
    if (!arguments.length) return height;
    height = value;
    return my;
  };

  return my;
}
3456789101112131415234567891011
var data = [
        {x: 10.0, y: 9.14},
        {x:  8.0, y: 8.14},
        {x: 13.0, y: 8.74},
        {x:  9.0, y: 8.77},
        {x: 11.0, y: 9.26},
        {x: 14.0, y: 8.10},
        {x:  6.0, y: 6.13},
        {x:  4.0, y: 3.10},
        {x: 12.0, y: 9.13},
        {x:  7.0, y: 7.26},
        {x:  5.0, y: 4.74},
      ];

      var mydotChart = dotChart( { width: 800, height: 600 });

      mydotChart( d3.select("#dot-chart2").datum(data) );
      //or 
     d3.select("#dot-chart2").datum(data).call(mydotChart);
function dotChart(config) {
    
  var margin = {
                    top: config.margin_top || 80, 
                    right: config.margin_right || 80, 
                    bottom: config.margin_bottom || 200, 
                    left: config.margin_left || 80
                },
                width = config.width || 1280,
                height = config.height || 720;

  var x = d3.scale.linear()
      .range([0, width - margin.left - margin.right]);

  var y = d3.scale.linear()
      .range([height - margin.top - margin.bottom, 0]);

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickPadding(8);

  var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left")
      .tickPadding(8);

  function chart(selection) {
    selection.each(function(d) {

      pad(x.domain(d3.extent(d, xValue)), 40);
      pad(y.domain(d3.extent(d, yValue)), 40);

      var svg = d3.select(this).append("svg")
          .attr("width", width)
          .attr("height", height)
          .attr("class", "dot chart")
        .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      svg.selectAll(".dot")
          .data(d)
        .enter().append("circle")
          .attr("class", "dot")
          .attr("cx", function(d) { return x(d.x); })
          .attr("cy", function(d) { return y(d.y); })
          .attr("r", 12);

      svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + y.range()[0] + ")")
          .call(xAxis);

      svg.append("g")
          .attr("class", "y axis")
          .call(yAxis);

    });
  }

  function pad(scale, k) {
    var range = scale.range();
    if (range[0] > range[1]) k *= -1;
    return scale.domain([range[0] - k, range[1] + k].map(scale.invert)).nice();
  }

  function xValue(d) {
    return d.x;
  }

  function yValue(d) {
    return d.y;
  }

  return chart;
}

THE END

You can download this presentation here

https://github.com/cminatti/d3js.git