block by renecnielsen d5bd0980421481061326

Reusable Bubble Chart

Full Screen

This is an example of the d3Kit factory, which help you create a reusable chart.

Try it by

forked from kristw‘s block: Reusable Bubble Chart

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Reusable Bubble Chart</title>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <div id="chart"></div>

    <script src="//d3js.org/d3.v3.min.js" type="text/javascript"></script>
    <script src="https://rawgit.com/kristw/75b61f9beeab9b530612/raw/389e984e4041117a9185cf6edad9f6b85a38097a/d3kit.min.js" type="text/javascript"></script>
    <script src="main.js"></script>
  </body>
</html>

main.js

// Define bubble chart
var BubbleChart = d3Kit.factory.createChart(
  // First argument is the default options for this chart
  {
    margin: {top: 60, right: 60, bottom: 60, left: 60},
    initialWidth: 800,
    initialHeight: 460
  },
  // The second argument is an Array that contains
  // names of custom events from this chart.
  // In this example chart,
  // it will dispatch event "bubbleClick" when users click on a bubble.
  ['bubbleClick'],
  // The third argument is an internal constructor.
  // This is where you would implement a bubble chart
  // inside the passed skeleton.
  function(skeleton){
    var layers = skeleton.getLayerOrganizer();
    var dispatch = skeleton.getDispatcher();
    var color = d3.scale.category10();

    layers.create(['content', 'x-axis', 'y-axis']);

    var x = d3.scale.linear()
      .range([0, skeleton.getInnerWidth()]);

    var y = d3.scale.linear()
      .range([0, skeleton.getInnerHeight()]);

    var xAxis = d3.svg.axis()
      .scale(x)
      .orient('bottom');

    var yAxis = d3.svg.axis()
      .scale(y)
      .orient('left');

    var visualize = d3Kit.helper.debounce(function(){
      if(!skeleton.hasData()){
        d3Kit.helper.removeAllChildren(layers.get('content'));
        return;
      }
      var data = skeleton.data();

      x.domain(d3.extent(data, function(d){return d.x;}))
        .range([0, skeleton.getInnerWidth()]);
      y.domain(d3.extent(data, function(d){return d.y;}))
        .range([skeleton.getInnerHeight(), 0]);

      layers.get('x-axis')
        .attr('transform', 'translate(0,' + skeleton.getInnerHeight() + ')')
        .call(xAxis);

      layers.get('y-axis')
        .call(yAxis);

      var selection = layers.get('content').selectAll('circle')
        .data(data);

      selection.exit().remove();

      selection.enter().append('circle')
        .attr('cx', function(d){return x(d.x);})
        .attr('cy', function(d){return y(d.y);})
        .on('click', dispatch.bubbleClick);

      selection
        .attr('cx', function(d){return x(d.x);})
        .attr('cy', function(d){return y(d.y);})
        .attr('r', function(d){return d.r;})
        .style('fill', function(d, i){return color(i);});

    }, 10);

    skeleton
      .autoResize('width')
      .on('resize', visualize)
      .on('data', visualize);
  }
);

//---------------------------------------------------
// Use the bubble chart
//---------------------------------------------------

// Generate random data
var bubbles = [];

for(var i=0;i<100;i++){
  bubbles.push({
    x: Math.random()*100,
    y: Math.random()*100,
    r: Math.random()*5+3
  });
}

new BubbleChart('#chart')
  .data(bubbles)
  // handle bubbleClick event
  .on('bubbleClick', function(d){ alert(JSON.stringify(d)); });

style.css

body {
  font: 10px sans-serif;
}

.x-axis-layer line, .y-axis-layer line,
.x-axis-layer path, .y-axis-layer path {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}