HighChart:带有下拉列表的堆积柱形图

时间:2016-02-19 06:06:54

标签: javascript d3.js highcharts crossfilter stacked-chart

我正在尝试使用d3.js

复制this example

到目前为止,我已设法构建一个显示所有数据的堆积条形图,但我的目的是过滤csv并根据用户在组合中选择国家/地区将新数据绑定到我的图表。

这是我的代码:

  var outerWidth = 500;
  var outerHeight = 250;
  var margin = { left: 90, top: 30, right: 30, bottom: 40 };
  var barPadding = 0.2;
  var xColumn = "City";
  var yColumn = "Population";
  var colorColumn = "Year";
  var layerColumn = colorColumn;
  var innerWidth  = outerWidth  - margin.left - margin.right;
  var innerHeight = outerHeight - margin.top  - margin.bottom;
  var svg = d3.select("body").append("svg")
    .attr("width",  outerWidth)
    .attr("height", outerHeight);
  var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  var xAxisG = g.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + innerHeight + ")");
  var yAxisG = g.append("g")
    .attr("class", "y axis");
  var xScale = d3.scale.ordinal().rangeBands([0, innerWidth], barPadding);
  var yScale = d3.scale.linear().range([innerHeight, 0]);
  var colorScale = d3.scale.category10();
  // Use a modified SI formatter that uses "B" for Billion.
  var siFormat = d3.format("s");
  var customTickFormat = function (d){
    return siFormat(d).replace("G", "B");
  };
  var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
    .outerTickSize(0);
  var yAxis = d3.svg.axis().scale(yScale).orient("left")
    .ticks(5)
    .tickFormat(customTickFormat)
    .outerTickSize(0);
  function render(data){
    var nested = d3.nest()
      .key(function (d){ return d[layerColumn]; })
      .entries(data)
    var stack = d3.layout.stack()
      .y(function (d){ return d[yColumn]; })
      .values(function (d){ return d.values; });
    var layers = stack(nested);
    xScale.domain(layers[0].values.map(function (d){
      return d[xColumn];
    }));
    yScale.domain([
      0,
      d3.max(layers, function (layer){
        return d3.max(layer.values, function (d){
          return d.y0 + d.y;
        });
      })
    ]);
    colorScale.domain(layers.map(function (layer){
      return layer.key;
    }));
    xAxisG.call(xAxis);
    yAxisG.call(yAxis);
    var layerGroups = g.selectAll(".layer").data(layers);
    layerGroups.enter().append("g").attr("class", "layer");
    layerGroups.exit().remove();
    layerGroups.style("fill", function (d){
      return colorScale(d.key);
    });
    var bars = layerGroups.selectAll("rect").data(function (d){
      return d.values;
    });
    bars.enter().append("rect")
    bars.exit().remove();
    bars
      .attr("x", function (d){ return xScale(d[xColumn]); })
      .attr("y", function (d){ return yScale(d.y0 + d.y); })
      .attr("width", xScale.rangeBand())
      .attr("height", function (d){ return innerHeight - yScale(d.y); })
  }
  function type(d){
    d.Population = +d.Population;
    return d;
  }
  d3.csv("data.csv", type, render);
</script>

以下是data.csv中的示例数据

Country City Year Population

US     Dallas 2010 1000
US     Dallas 2011 1200
UK     London 2010 700
UK     London 2011  850
US     Chicago  2010 1250
US     Chicago  2011  1300

1 个答案:

答案 0 :(得分:0)

可以通过重新加载和重新分析CSV并使用Highcharts官方data module来重新加载图表数据,但是加载和解析数据一次更有效,下次更新/重建图表需要时。

Example: http://jsfiddle.net/1wgqyyg9/

&#13;
&#13;
// Emulate get
$.get = function(id, fn) {
  fn(document.getElementById(id).innerHTML);
};

$(function() {
		var chartOptions = {
      chart: {
        type: 'column'
      },
      xAxis: {
        type: 'category'
      },
      yAxis: {
        min: 0,
        title: {
          text: 'Total population over years'
        },
        stackLabels: {
          enabled: true,
          style: {
            fontWeight: 'bold',
            color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
          }
        }
      },
      legend: {
        align: 'right',
        x: -30,
        verticalAlign: 'top',
        y: 25,
        floating: true,
        backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
        borderColor: '#CCC',
        borderWidth: 1,
        shadow: false
      },
      tooltip: {
        headerFormat: '<b>{series.name}</b><br/>',
        pointFormat: '{point.name}: {point.y}<br/>Total: {point.stackTotal}'
      },
      plotOptions: {
        column: {
          stacking: 'normal',
          dataLabels: {
            enabled: true,
            color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
            style: {
              textShadow: '0 0 3px black'
            }
          }
        }
      },
      series: []
    };

  //load CSV - emulated infile to show in JSFiddle
  $.get('data.csv', function(data) {
    // Split the lines
    var lines = data.split('\n'),
      	countries = {};

    // Iterate over the lines and create data sets - countries
    $.each(lines, function(lineNo, line) {
      var items = line.split(','),
      		yearFound = false,
      		country, city, year, population;

      if (lineNo === 0) {  // header line containes info
      } 									// rest of lines contain data
      else {
      	country = items[0],
        city = items[1],
        year = items[2],
        population = items[3];
      	// check if new country
        if(countries[country] === undefined) {
        	countries[country] = [{
          	name: year,
            data: [{name: city, y: parseInt(population)}]
          }];
        } else {
        	$.each(countries[country], function(yearNo, countryYear){
          	if(year === countryYear.name) {
            	yearFound = true;
              countryYear.data.push({name: city, y: parseInt(population)});
            	return false; //exit this each loop
            }
          });
          if(!yearFound) { // new year
          	countries[country].push({
            	name: year,
            	data: [{name: city, y: parseInt(population)}]
            });
          }
        }
      }
    });
    // sort cities in year series
    $.each(countries, function(countryName,country){
    	$('#selectCountry')
         .append($("<option></option>")
         .attr("value",countryName)
         .text(countryName)); 
         
    	$.each(country, function(j,year){
      	year.data.sort(function(a,b){
        	a.name > b.name;
        });
      });
    });
    
    $("#selectCountry").change(function(){ 
        var selected = this.value;
        if(selected) {
          chartOptions.series = $.extend(true, [], countries[selected]); // do deep copy to keep original data
          Highcharts.chart('container',chartOptions);
        }
    });
  });
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>

<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

<select id="selectCountry">
  <option>Select country</option>
</select>

<pre id="data.csv" style="display: none">Country,City,Year,Population
US,Dallas,2010,1000
US,Dallas,2011,1200
UK,London,2010,700
UK,London,2011,850
US,Chicago,2010,1250
US,Chicago,2011,1300</pre>
&#13;
&#13;
&#13;

相关问题