bar_chart.html revision cef7893435aa41160dd1255c43cb8498279738cc
1<!DOCTYPE html>
2<!--
3Copyright (c) 2014 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/ui/base/chart_base_2d_brushable_x.html">
9
10<script>
11'use strict';
12
13tr.exportTo('tr.ui.b', function() {
14  var ColorScheme = tr.b.ColorScheme;
15  var ChartBase2DBrushX = tr.ui.b.ChartBase2DBrushX;
16  var getColorOfKey = tr.ui.b.getColorOfKey;
17
18  // @constructor
19  var BarChart = tr.ui.b.define('bar-chart', ChartBase2DBrushX);
20
21  BarChart.prototype = {
22    __proto__: ChartBase2DBrushX.prototype,
23
24    decorate: function() {
25      ChartBase2DBrushX.prototype.decorate.call(this);
26      this.classList.add('bar-chart');
27      this.xCushion_ = 0;
28    },
29
30    isDatumFieldSeries_: function(fieldName) {
31      return fieldName != 'x';
32    },
33
34    getXForDatum_: function(datum, index) {
35      return datum.x;
36    },
37
38    updateScales_: function() {
39      if (this.data_.length === 0)
40        return;
41
42      var xDifferences = 0;
43      var currentX = undefined;
44      var previousX = undefined;
45      var yRange = new tr.b.Range();
46      this.data_.forEach(function(datum, index) {
47        previousX = currentX;
48        currentX = this.getXForDatum_(datum, index);
49        if (previousX !== undefined) {
50          xDifferences += currentX - previousX;
51        }
52
53        this.seriesKeys_.forEach(function(key) {
54          // Allow for sparse data
55          if (datum[key] !== undefined)
56            yRange.addValue(datum[key]);
57        });
58      }, this);
59
60      // X.
61      // Leave a cushion on the right so that the last rect doesn't
62      // exceed the chart boundaries. The last rect's width is set to the
63      // average width of the rects, which is chart.width / data.length.
64      var width = this.chartAreaSize.width;
65      this.xScale_.range([0, width]);
66      var domain = d3.extent(this.data_, this.getXForDatum_.bind(this));
67      this.xCushion_ = xDifferences / (this.data_.length - 1);
68      this.xScale_.domain([domain[0], domain[1] + this.xCushion_]);
69
70      // Y.
71      this.yScale_.range([this.chartAreaSize.height, 0]);
72      this.yScale_.domain(this.getYScaleDomain_(yRange.min, yRange.max));
73    },
74
75    updateDataContents_: function(dataSel) {
76      dataSel.selectAll('*').remove();
77      var rectsSel = dataSel.selectAll('path').data(this.seriesKeys_);
78      this.data_.forEach(function(datum, index) {
79        var currentX = this.getXForDatum_(datum, index);
80        var width = undefined;
81        if (index < (this.data_.length - 1)) {
82          var nextX = this.getXForDatum_(this.data_[index + 1], index + 1);
83          width = nextX - currentX;
84        } else {
85          width = this.xCushion_;
86        }
87
88        var stacks = [];
89        this.seriesKeys_.forEach(function(key) {
90          if (datum[key] !== undefined)
91            stacks.push({y: datum[key], color: getColorOfKey(key)});
92        });
93        stacks.sort(function(a, b) {
94          return b.y - a.y;
95        });
96
97        stacks.forEach(function(stack) {
98          var left = this.xScale_(currentX);
99          var right = this.xScale_(currentX + width);
100          var widthPx = right - left;
101          var top = this.yScale_(Math.max(stack.y, this.getYScaleMin_()));
102          rectsSel.enter()
103              .append('rect')
104              .attr('fill', stack.color)
105              .attr('x', left)
106              .attr('y', top)
107              .attr('width', widthPx)
108              .attr('height', this.yScale_.range()[0] - top);
109        }, this);
110      }, this);
111      rectsSel.exit().remove();
112    }
113  };
114
115  return {
116    BarChart: BarChart
117  };
118});
119</script>
120