block by EE2dev 264df2edf12a0b95577fee517d2ac139

d3-template: barCharts

Full Screen

This example of d3-template is combining the approaches of:

index.html

<!DOCTYPE html>
  <meta charset="utf-8"> <!-- also save this file as unicode-8 ! -->
  <head>
    <script src="//d3js.org/d3.v3.js"></script>
    <link rel="stylesheet" type="text/css" href="d3_template_barCharts.css">
    <script src="d3_template_barCharts.js"></script>
   </head>
  
  <body>
    <div id="updatableChart"></div>

    <script>
      var dataSet = [];
      var highTemperatures = dataSet[0] = [77, 71, 82, 87, 84, 78, 80, 84, 86, 72, 71, 68, 75, 73, 80, 85, 86, 80];
      var lowTemperatures = dataSet[1] = highTemperatures.map(function(d) { return d - Math.random() * 30});
      var milesRun = dataSet[2] = [2, 5, 4, 3, 1, 2, 1];
      var fillColors = ['coral', 'steelblue', 'teal'];

      var myChart = reUsableChart("ht.csv").width(800) // no parameter when data is embedded in <pre> tag, otherwise reUsableChart(file);
        showChart(); // for preprocessing data see below

      window.setTimeout(function() {
          myChart.height(450);
      }, 5000);

      var i = 1;
      window.setInterval(function() {
        console.log("hier" + i);
          // updatableChart.data(dataSet[i]);
          myChart.height(150 * (i+1));
          myChart.fillColor(fillColors[i]);
          
          i = (i+1) % 3 ;
      }, 2500);
      
      function showChart(_file, preprocessed) {
        var selection = d3.select("body")
          .append("div")
          .attr("class", "chart");
        if (preprocessed) {
          selection.datum(_file);
        }
        selection.call(myChart);
      }         
    
      /*
      ////////////////////////////////////////////////////////////////
      //  If data needs to be processed before passing it on        //
      //  substitute showChart() with readData()                    //
      ////////////////////////////////////////////////////////////////

      readData(); // no parameter when data is embedded in <pre> tag, otherwise readData(file);
      
      function readData(csvFile) {
        if (typeof csvFile !== 'undefined') {
          d3.csv(csvFile, processData, function(error, file) {
            showChart(file, true);
          });
        } 
        else {
          file = d3.csv.parse(d3.select("pre#data").text()); 
          file.forEach( function (row) {
            processData(row);
          });        
          showChart(file, true);
        }
      } 
      
      ////////////////////////////////////////////////////////////////
      //  This function converts each data element to a number.      //
      //  Update this function to process data accordingly          //
      ////////////////////////////////////////////////////////////////
       
      function processData(d) {
        for (var perm in d) {
          if (Object.prototype.hasOwnProperty.call(d, perm)) {
            d[perm] = +d[perm];
          }
        }    
        return d;
      }  
      */
    </script>
  </body>
</html>  

d3_template_barCharts.css

    .unselect {
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    
    div.chart {
      width: 100%;
      height: 100%;
    }
    
    pre#data {
      display:none;
    }
    
    div.center {
      width: 850px;
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    
    svg.Chart {
      display: block;
      margin: auto;
    }
    
    body {
      padding: 20px 0 0 10px;
    }

d3_template_barCharts.js

var reUsableChart = function(_myData) {
  "use strict";
  var file; // reference to data (embedded or in file)
  
  ///////////////////////////////////////////////////
  // 1.0 add visualization specific variables here //
  ///////////////////////////////////////////////////
  
  // 1.1 All options that should be accessible to caller
  var width = 500;
  var height = 300;
  var barPadding = 1;
  var fillColor = 'coral';
  var data = [];

  // 1.2 all updatable functions to be called by getter-setter methods
  var updateWidth;
  var updateHeight;
  var updateFillColor;
  var updateData;
    
  ////////////////////////////////////////////////////
  // 2.0 add getter-setter methods here             //
  //////////////////////////////////////////////////// 
  
  // API - example for getter-setter method
  chartAPI.width = function(value) {
      if (!arguments.length) return width;
      width = value;
      if (typeof updateWidth === 'function') updateWidth();
      return chartAPI;
  };

  chartAPI.height = function(value) {
      if (!arguments.length) return height;
      height = value;
      if (typeof updateHeight === 'function') updateHeight();
      return chartAPI;
  };

  chartAPI.fillColor = function(value) {
      if (!arguments.length) return fillColor;
      fillColor = value;
      if (typeof updateFillColor === 'function') updateFillColor();
      return chartAPI;
  };

  chartAPI.data = function(value) {
      if (!arguments.length) return data;
      data = value;
      if (typeof updateData === 'function') updateData();
      return chartAPI;
  };
    
  ////////////////////////////////////////////////////
  // 3.0 add visualization specific processing here //
  //////////////////////////////////////////////////// 
  
  function createChart(selection, _file) {
    var data = _file;
    console.log(data);
    selection.each(function () {
      // 2.1 insert code here
      var barSpacing = height / data.length;
      var barHeight = barSpacing - barPadding;
      var maxValue = d3.max(data, function(d) { return d.high;});
      var widthScale = width / maxValue;

      var dom = d3.select(this);
      var svg = dom.append('svg')
        .attr('class', 'bar-chart')
        .attr('height', height)
        .attr('width', width)
        .style('fill', fillColor);

      var bars = svg.selectAll('rect.display-bar')
        .data(data)
        .enter()
        .append('rect')
        .attr('class', 'display-bar')
        .attr('y', function (d, i) { return i * barSpacing;  })
        .attr('height', barHeight)
        .attr('x', 0)
        .attr('width', function (d) { return d.high * widthScale; });

      // 2.2 update functions
      updateWidth = function() {
        widthScale = width / maxValue;
        bars.transition().duration(1000).attr('width', function(d) { return d * widthScale; });
        svg.transition().duration(1000).attr('width', width);
      };

      updateHeight = function() {
        console.log("--height");
        barSpacing = height / data.length;
        barHeight = barSpacing - barPadding;
        bars.transition().duration(1000).attr('y', function(d, i) { return i * barSpacing; })
          .attr('height', barHeight);
        svg.transition().duration(1000).attr('height', height);
      };

      updateFillColor = function() {
        svg.transition().duration(1000).style('fill', fillColor);
      };

      updateData = function() {
        barSpacing = height / data.length;
        barHeight = barSpacing - barPadding;
        maxValue = d3.max(data);
        widthScale = width / maxValue;

        var update = svg.selectAll('rect.display-bar')
          .data(data);

        update
          .transition()
          .duration(1000)
          .attr('y', function(d, i) { return i * barSpacing; })
          .attr('height', barHeight)
          .attr('x', 0)
          .attr('width', function(d) { return d * widthScale; });

        update.enter()
          .append('rect')
          .attr('class', 'display-bar')
          .attr('y', function(d, i) { return i * barSpacing; })
          .attr('height', barHeight)
          .attr('x', 0)
          .attr('width', 0)
          .style('opacity', 0)
          .transition()
          .duration(1000)
          .delay(function(d, i) { return (data.length - i) * 40; })
          .attr('width', function(d) { return d * widthScale; })
          .style('opacity', 1);

        update.exit()
          .transition()
          .duration(650)
          .delay(function(d, i) { return (data.length - i) * 20; })
          .style('opacity', 0)
          .attr('height', 0)
          .attr('x', 0)
          .attr('width', 0)
          .remove();
      }        
    });
  }

  ////////////////////////////////////////////////////
  // General API template begins here               //
  //////////////////////////////////////////////////// 
  
  // functions for external access
  function chartAPI(selection) {
    selection.each( function (d) {
      console.log(d);
      console.log("_myData "+ _myData);
      if (typeof d !== 'undefined') { // data processing from outside
        createChart(selection, d);
      }
      else { // data processing here
        if (typeof _myData !== 'undefined') { 
          readData(_myData, selection);
        } 
        else {
          readData("<pre>", selection);
        }
      }
    });
  }
      
  // XHR to load data   
  function readData(csvFile, selection) {
    if (csvFile !== "<pre>") {
      d3.csv(csvFile, convertToNumber, function(error, f) {
        createChart(selection, f);
      });
    } 
    else {
      file = d3.csv.parse(d3.select("pre#data").text()); 
      file.forEach( function (row) {
        convertToNumber(row);
      });
      console.log(file);
      createChart(selection, file);
    }
  } 

  // helper for XHR
  function convertToNumber(d) {
    for (var perm in d) {
        if (Object.prototype.hasOwnProperty.call(d, perm)) {
          d[perm] = +d[perm];
        }
      }  
    return d;
  } 
    
  return chartAPI;
};

ht.csv

high
77
71
82
87
84
78
80
84
86
72
71
68
75
73
80
85
86
80