Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Architecting Better Charts, FluentConf 2013 Keynote

Architecting Better Charts, FluentConf 2013 Keynote

Announcing the Miso Project's latest library, d3.chart - a framework for building reusable charts with d3.js.
http://misoproject.com/d3-chart

Video: http://www.youtube.com/watch?feature=player_embedded&v=TYgSc_S0lCw&list=SP055Epbe6d5avZGXwE5u039VQq_oQFgrc

F99c66cc9f64454df105006286d47521?s=128

Irene Ros

May 29, 2013
Tweet

More Decks by Irene Ros

Other Decks in Technology

Transcript

  1. The ABC of Data Visualization Irene Ros @ireneros Mike Pennisi

    @jugglinmike http://bocoup.com http://misoproject.com
  2. The ABC of Data Visualization Irene Ros @ireneros Mike Pennisi

    @jugglinmike http://bocoup.com http://misoproject.com Architecting Better Charts
  3. None
  4. Cleanup

  5. Cleanup Transformation

  6. Cleanup Transformation Analysis

  7. Cleanup Transformation Analysis Visualization

  8. Cleanup Transformation Analysis Visualization

  9. Cleanup Transformation Analysis Visualization Is it good enough? Is the

    story right? Is the conclusion correct? Is it the right message? No
  10. Cleanup Transformation Analysis Visualization Is it good enough? Is the

    story right? Is the conclusion correct? Is it the right message? No Yes! Build it! On the web!
  11. We d3.js

  12. None
  13. The Code Spaghetti Monster!

  14. ? What does it mean to Architect Data Visualization

  15. Making Reusable Charts Towards Reusable Charts http://bost.ocks.org/mike/chart/

  16. Repeatable Easy to create multiple instances of What is a

    reusable chart? Difficulty level:
  17. Repeatable Easy to create multiple instances of What is a

    reusable chart? Difficulty level: BarChart Constructor
  18. Repeatable Easy to create multiple instances of What is a

    reusable chart? Difficulty level: BarChart Constructor
  19. Configurable Easy to appropriate for a specific task What is

    a reusable chart? Difficulty level:
  20. Configurable Easy to appropriate for a specific task What is

    a reusable chart? Difficulty level: BarChart Constructor
  21. Configurable Easy to appropriate for a specific task What is

    a reusable chart? Difficulty level: BarChart Constructor
  22. Extensible Easy to extend with additional functionality What is a

    reusable chart? Difficulty level:
  23. Extensible Easy to extend with additional functionality What is a

    reusable chart? Difficulty level: BarChart Constructor
  24. Extensible Easy to extend with additional functionality What is a

    reusable chart? Difficulty level: BarChart Constructor 10 20 60 30
  25. Composable Easy to combine into other charts What is a

    reusable chart? Difficulty level:
  26. Composable Easy to combine into other charts What is a

    reusable chart? Difficulty level: BarChart Constructor
  27. Composable Easy to combine into other charts What is a

    reusable chart? Difficulty level: BarChart Constructor Axis Constructor +
  28. Composable Easy to combine into other charts What is a

    reusable chart? Difficulty level: BarChart Constructor Axis Constructor + Label Constructor 10 40 30 1 +
  29. Composable Easy to combine into other charts What is a

    reusable chart? Difficulty level: BarChart Constructor Axis Constructor + Label Constructor 10 40 30 1 + 10 20 60 30 =
  30. A Announcement Big

  31. A Announcement Big

  32. http://misoproject.com/d3-chart http://github.com/misoproject/d3.chart http://blog.bocoup.com Code: Announcement:

  33. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  34. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  35. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  36. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  37. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  38. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  39. Unpacking d3: var data = [1,3,4,6,10]; var chart = d3.select("#vis")

    .append("svg") .attr("height", 200) .attr("width", 200); var circles = chart.append("g") .classed("circles", true) .selectAll("circle") .data(data) .enter() .append("circle") .attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue");
  40. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  41. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  42. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  43. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  44. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  45. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  46. Now in d3.chart d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"),

    { dataBind: function(data) { return this.selectAll("circle") .data(data); }, insert: function() { return this.append("circle"); }, events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", "blue"); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw(data);
  47. Repeatable var chart2 = d3.select("#vis2") .append("svg") .attr("height", 1000) .attr("width", 1000)

    .chart("CircleChart"); chart2.draw([10,20,400]); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart"); chart1.draw([1,2,4]);
  48. Configurable Configurable d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"), {

    // other layer instructions... events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", this.chart().fill()); } } }); }, fill: function(newFill) { if (arguments.length === 0) { return this._fill; } this._fill = newFill; return this; } });
  49. Configurable Configurable d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"), {

    // other layer instructions... events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", this.chart().fill()); } } }); }, fill: function(newFill) { if (arguments.length === 0) { return this._fill; } this._fill = newFill; return this; } });
  50. Configurable Configurable d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"), {

    // other layer instructions... events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", this.chart().fill()); } } }); }, fill: function(newFill) { if (arguments.length === 0) { return this._fill; } this._fill = newFill; return this; } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CircleChart") .fill("blue"); chart1.draw(data);
  51. Configurable Extensible d3.chart("CircleChart").extend("CirclesWithNumbersChart", { initialize: function() { this.layer("labels", this.base.append("g"), {

    dataBind: function(data) { return this.selectAll("text") .data(data); }, insert: function() { return this.append("text"); }, events: { enter: function() { return this.attr("x", function(d) { return d * 10; }) .attr("y", 80) .style("text-anchor", "middle") .text(function(d) { return d; }); } } }); } });
  52. Extensible d3.chart("CircleChart").extend("CirclesWithNumbersChart", { initialize: function() { this.layer("labels", this.base.append("g"), { dataBind:

    function(data) { return this.selectAll("text") .data(data); }, insert: function() { return this.append("text"); }, events: { enter: function() { return this.attr("x", function(d) { return d * 10; }) .attr("y", 80) .style("text-anchor", "middle") .text(function(d) { return d; }); } } }); } });
  53. Extensible d3.chart("CircleChart").extend("CirclesWithNumbersChart", { initialize: function() { this.layer("labels", this.base.append("g"), { dataBind:

    function(data) { return this.selectAll("text") .data(data); }, insert: function() { return this.append("text"); }, events: { enter: function() { return this.attr("x", function(d) { return d * 10; }) .attr("y", 80) .style("text-anchor", "middle") .text(function(d) { return d; }); } } }); } });
  54. Extensible d3.chart("CircleChart").extend("CirclesWithNumbersChart", { initialize: function() { this.layer("labels", this.base.append("g"), { dataBind:

    function(data) { return this.selectAll("text") .data(data); }, insert: function() { return this.append("text"); }, events: { enter: function() { return this.attr("x", function(d) { return d * 10; }) .attr("y", 80) .style("text-anchor", "middle") .text(function(d) { return d; }); } } }); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CirclesWithNumbersChart") .fill("blue");
  55. Composable

  56. Composable d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"), { //

    other layer instructions... events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", this.chart().fill()); } } }); }, fill: function(newFill) { if (arguments.length === 0) { return this._fill; } this._fill = newFill; return this; } });
  57. Composable d3.chart("LabelsChart", { initialize: function() { this.layer("labels", this.base.append("g"), { dataBind:

    function(data) { return this.selectAll("text") .data(data); }, insert: function() { return this.append("text"); }, events: { enter: function() { return this.attr("x", function(d) { return d * 10; }) .attr("y", 80) .style("text-anchor", "middle") .text(function(d) { return d; }); } } }); } }); d3.chart("CircleChart", { initialize: function() { this.layer("circles", this.base.append("g"), { // other layer instructions... events : { enter: function() { return this.attr("cy", 100) .attr("cx", function(d) { return d * 10; }) .attr("r", 5) .style("fill", this.chart().fill()); } } }); }, fill: function(newFill) { if (arguments.length === 0) { return this._fill; } this._fill = newFill; return this; } });
  58. Composable d3.chart("CLChart", { initialize: function() { var circles = this.mixin(

    this.base.append("g"), "CircleChart" ); var labels = this.mixin( this.base.append("g"), "LabelsChart" ); } });
  59. Composable d3.chart("CLChart", { initialize: function() { var circles = this.mixin(

    this.base.append("g"), "CircleChart" ); var labels = this.mixin( this.base.append("g"), "LabelsChart" ); } });
  60. Composable d3.chart("CLChart", { initialize: function() { var circles = this.mixin(

    this.base.append("g"), "CircleChart" ); var labels = this.mixin( this.base.append("g"), "LabelsChart" ); } });
  61. Composable d3.chart("CLChart", { initialize: function() { var circles = this.mixin(

    this.base.append("g"), "CircleChart" ); var labels = this.mixin( this.base.append("g"), "LabelsChart" ); } }); var chart1 = d3.select("#vis") .append("svg") .attr("height", 200) .attr("width", 200) .chart("CLChart"); chart1.draw(data);
  62. Let’s All Build Charts! http://github.com/misoproject/d3.chart http://misoproject.com/d3-chart Irene Ros @ireneros Mike

    Pennisi @jugglinmike http://bocoup.com http://misoproject.com