kibana-123
Version:
Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic
246 lines (206 loc) • 7.11 kB
JavaScript
import _ from 'lodash';
import moment from 'moment';
import errors from 'ui/errors';
import VislibVisualizationsPointSeriesProvider from './_point_series';
export default function ColumnChartFactory(Private) {
const PointSeries = Private(VislibVisualizationsPointSeriesProvider);
const defaults = {
mode: 'normal',
showTooltip: true,
color: undefined,
fillColor: undefined
};
/**
* Vertical Bar Chart Visualization: renders vertical and/or stacked bars
*
* @class ColumnChart
* @constructor
* @extends Chart
* @param handler {Object} Reference to the Handler Class Constructor
* @param el {HTMLElement} HTML element to which the chart will be appended
* @param chartData {Object} Elasticsearch query results for this specific chart
*/
class ColumnChart extends PointSeries {
constructor(handler, chartEl, chartData, seriesConfigArgs) {
super(handler, chartEl, chartData, seriesConfigArgs);
this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults);
}
addBars(svg, data) {
const self = this;
const color = this.handler.data.getColorFunc();
const tooltip = this.baseChart.tooltip;
const isTooltip = this.handler.visConfig.get('tooltip.show');
const layer = svg.append('g')
.attr('class', 'series')
.attr('clip-path', 'url(#' + this.baseChart.clipPathId + ')');
const bars = layer.selectAll('rect')
.data(data.values);
bars
.exit()
.remove();
bars
.enter()
.append('rect')
.attr('data-label', data.label)
.attr('fill', () => {
return color(data.label);
});
self.updateBars(bars);
// Add tooltip
if (isTooltip) {
bars.call(tooltip.render());
}
return bars;
};
/**
* Determines whether bars are grouped or stacked and updates the D3
* selection
*
* @method updateBars
* @param bars {D3.UpdateSelection} SVG with rect added
* @returns {D3.UpdateSelection}
*/
updateBars(bars) {
if (this.seriesConfig.mode === 'stacked') {
return this.addStackedBars(bars);
}
return this.addGroupedBars(bars);
};
/**
* Adds stacked bars to column chart visualization
*
* @method addStackedBars
* @param bars {D3.UpdateSelection} SVG with rect added
* @returns {D3.UpdateSelection}
*/
addStackedBars(bars) {
const xScale = this.getCategoryAxis().getScale();
const yScale = this.getValueAxis().getScale();
const isHorizontal = this.getCategoryAxis().axisConfig.isHorizontal();
const isTimeScale = this.getCategoryAxis().axisConfig.isTimeDomain();
const height = yScale.range()[0];
const yMin = yScale.domain()[0];
const groupSpacingPercentage = 0.15;
const groupCount = this.getGroupedCount();
const groupNum = this.getGroupedNum(this.chartData);
let barWidth;
if (isTimeScale) {
const {min, interval} = this.handler.data.get('ordered');
let groupWidth = xScale(min + interval) - xScale(min);
if (!isHorizontal) groupWidth *= -1;
const groupSpacing = groupWidth * groupSpacingPercentage;
barWidth = (groupWidth - groupSpacing) / groupCount;
}
function x(d) {
const groupPosition = isTimeScale ? barWidth * groupNum : xScale.rangeBand() / groupCount * groupNum;
return xScale(d.x) + groupPosition;
}
function y(d) {
if ((isHorizontal && d.y < 0) || (!isHorizontal && d.y > 0)) {
return yScale(d.y0);
}
/*if (!isHorizontal && d.y < 0) return yScale(d.y);*/
return yScale(d.y0 + d.y);
}
function widthFunc() {
return isTimeScale ? barWidth : xScale.rangeBand() / groupCount;
}
function heightFunc(d) {
// for split bars or for one series,
// last series will have d.y0 = 0
if (d.y0 === 0 && yMin > 0) {
return yScale(yMin) - yScale(d.y);
}
return Math.abs(yScale(d.y0) - yScale(d.y0 + d.y));
}
// update
bars
.attr('x', isHorizontal ? x : y)
.attr('width', isHorizontal ? widthFunc : heightFunc)
.attr('y', isHorizontal ? y : x)
.attr('height', isHorizontal ? heightFunc : widthFunc);
return bars;
};
/**
* Adds grouped bars to column chart visualization
*
* @method addGroupedBars
* @param bars {D3.UpdateSelection} SVG with rect added
* @returns {D3.UpdateSelection}
*/
addGroupedBars(bars) {
const xScale = this.getCategoryAxis().getScale();
const yScale = this.getValueAxis().getScale();
const groupCount = this.getGroupedCount();
const groupNum = this.getGroupedNum(this.chartData);
const height = yScale.range()[0];
const groupSpacingPercentage = 0.15;
const isTimeScale = this.getCategoryAxis().axisConfig.isTimeDomain();
const isHorizontal = this.getCategoryAxis().axisConfig.isHorizontal();
const isLogScale = this.getValueAxis().axisConfig.isLogScale();
const minWidth = 1;
let barWidth;
if (isTimeScale) {
const {min, interval} = this.handler.data.get('ordered');
let groupWidth = xScale(min + interval) - xScale(min);
if (!isHorizontal) groupWidth *= -1;
const groupSpacing = groupWidth * groupSpacingPercentage;
barWidth = (groupWidth - groupSpacing) / groupCount;
}
function x(d) {
if (isTimeScale) {
return xScale(d.x) + barWidth * groupNum;
}
return xScale(d.x) + xScale.rangeBand() / groupCount * groupNum;
}
function y(d) {
if ((isHorizontal && d.y < 0) || (!isHorizontal && d.y > 0)) {
return yScale(0);
}
return yScale(d.y);
}
function widthFunc() {
if (barWidth < minWidth) {
throw new errors.ContainerTooSmall();
}
if (isTimeScale) {
return barWidth;
}
return xScale.rangeBand() / groupCount;
}
function heightFunc(d) {
const baseValue = isLogScale ? 1 : 0;
return Math.abs(yScale(baseValue) - yScale(d.y));
}
// update
bars
.attr('x', isHorizontal ? x : y)
.attr('width', isHorizontal ? widthFunc : heightFunc)
.attr('y', isHorizontal ? y : x)
.attr('height', isHorizontal ? heightFunc : widthFunc);
return bars;
};
/**
* Renders d3 visualization
*
* @method draw
* @returns {Function} Creates the vertical bar chart
*/
draw() {
const self = this;
return function (selection) {
selection.each(function () {
const svg = self.chartEl.append('g');
svg.data([self.chartData]);
const bars = self.addBars(svg, self.chartData);
self.addCircleEvents(bars);
self.events.emit('rendered', {
chart: self.chartData
});
return svg;
});
};
};
}
return ColumnChart;
};