From 885dcb8d7b146f1dd9ae7f66a64513187feb49c9 Mon Sep 17 00:00:00 2001 From: Flavio Date: Tue, 12 Dec 2017 09:19:07 +0000 Subject: [PATCH 1/2] Grouped and Staked Bars --- src/bar-chart.js | 104 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/src/bar-chart.js b/src/bar-chart.js index 9775065a9..c0c2cebec 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -27,16 +27,21 @@ dc.barChart = function (parent, chartGroup) { var MIN_BAR_WIDTH = 1; var DEFAULT_GAP_BETWEEN_BARS = 2; + var DEFAULT_GAP_BETWEEN_BAR_SERIES = 5; var LABEL_PADDING = 3; + var _type = "dc.BAR_CHART"; var _chart = dc.stackMixin(dc.coordinateGridMixin({})); var _gap = DEFAULT_GAP_BETWEEN_BARS; + var _serieGap = DEFAULT_GAP_BETWEEN_BAR_SERIES; var _centerBar = false; var _alwaysUseRounding = false; var _barWidth; + + _chart.type = _type; dc.override(_chart, 'rescale', function () { _chart._rescale(); _barWidth = undefined; @@ -46,7 +51,7 @@ dc.barChart = function (parent, chartGroup) { dc.override(_chart, 'render', function () { if (_chart.round() && _centerBar && !_alwaysUseRounding) { dc.logger.warn('By default, brush rounding is disabled if bars are centered. ' + - 'See dc.js bar chart API documentation for details.'); + 'See dc.js bar chart API documentation for details.'); } return _chart._render(); @@ -81,11 +86,24 @@ dc.barChart = function (parent, chartGroup) { }); }; - function barHeight (d) { + function barHeight(d) { return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0))); } - function renderLabels (layer, layerIndex, d) { + + function getCharts() { + if (parent instanceof Object) { + if (parent.children() instanceof Array) { + return parent.children().filter(function (chart) { + return chart.type === _type; + }); + } + } + return []; + + } + + function renderLabels(layer, layerIndex, d) { var labels = layer.selectAll('text.barLabel') .data(d.values, dc.pluck('x')); @@ -102,8 +120,19 @@ dc.barChart = function (parent, chartGroup) { dc.transition(labels, _chart.transitionDuration(), _chart.transitionDelay()) .attr('x', function (d) { var x = _chart.x()(d.x); - if (!_centerBar) { - x += _barWidth / 2; + var charts = getCharts(); + if (charts.length > 1) { + x += _chart.serieGap() / 2; + x += layerIndex * (_barWidth + _gap); + x += _gap / 2; + } + x += _barWidth / 2; + if (_centerBar && !_chart.isOrdinal()) { + if (charts.length > 1) { + x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; + } else { + x -= _barWidth / 2; + } } return dc.utils.safeNumber(x); }) @@ -125,7 +154,7 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function renderBars (layer, layerIndex, d) { + function renderBars(layer, layerIndex, d) { var bars = layer.selectAll('rect.bar') .data(d.values, dc.pluck('x')); @@ -147,8 +176,19 @@ dc.barChart = function (parent, chartGroup) { dc.transition(bars, _chart.transitionDuration(), _chart.transitionDelay()) .attr('x', function (d) { var x = _chart.x()(d.x); - if (_centerBar) { - x -= _barWidth / 2; + var charts = getCharts(); + var chartIndex = charts.indexOf(_chart); + if (charts.length > 1) { + x += _chart.serieGap() / 2; + x += chartIndex * (_barWidth + _gap); + x += _gap / 2; + } + if (_centerBar && !_chart.isOrdinal()) { + if (charts.length > 1) { + x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; + } else { + x -= _barWidth / 2; + } } if (_chart.isOrdinal() && _gap !== undefined) { x += _gap / 2; @@ -177,19 +217,31 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function calculateBarWidth () { + function calculateBarWidth() { if (_barWidth === undefined) { var numberOfBars = _chart.xUnitCount(); - - // please can't we always use rangeBands for bar charts? - if (_chart.isOrdinal() && _gap === undefined) { - _barWidth = Math.floor(_chart.x().rangeBand()); - } else if (_gap) { - _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); + var charts = getCharts(); + if (charts.length > 1) { + var numberOfCharts = charts.length; + if (_chart.isOrdinal()) { + _barWidth = Math.floor((_chart.x().rangeBand() - _chart.serieGap()) / numberOfCharts - _gap); + } else { + _barWidth = Math.floor((_chart.xAxisLength() - (_chart.xUnitCount() - 1) * _chart.serieGap() - + (numberOfBars - 1) * (numberOfCharts) * _gap) / (numberOfBars * numberOfCharts)); + } } else { - _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); + // please can't we always use rangeBands for bar charts? + if (_chart.isOrdinal() && _gap === undefined) { + _barWidth = Math.floor(_chart.x().rangeBand()); + } else if (_gap) { + _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); + } else { + _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); + } } + + if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) { _barWidth = MIN_BAR_WIDTH; } @@ -299,6 +351,24 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; + /** + * Manually set fixed gap (in px) between bar groups instead of relying on the default auto-generated + * gap. Only applicable for grouped bar charts. + * @name serieGap + * @memberof dc.barChart + * @instance + * @param {Number} [serieGap=5] + * @return {Number} + * @return {dc.barChart} + */ + _chart.serieGap = function (serieGap) { + if (!arguments.length) { + return _serieGap; + } + _serieGap = serieGap; + return _chart; + }; + _chart.extendBrush = function () { var extent = _chart.brush().extent(); if (_chart.round() && (!_centerBar || _alwaysUseRounding)) { @@ -335,7 +405,7 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; - function colorFilter (color, inv) { + function colorFilter(color, inv) { return function () { var item = d3.select(this); var match = item.attr('fill') === color; From 296b5d08ee961f5687b6c41ab791cc344ce865a8 Mon Sep 17 00:00:00 2001 From: Flavio Date: Wed, 13 Dec 2017 09:44:46 +0000 Subject: [PATCH 2/2] Change validation of parent in bar chart --- src/bar-chart.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bar-chart.js b/src/bar-chart.js index c0c2cebec..49df89f9a 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -42,6 +42,7 @@ dc.barChart = function (parent, chartGroup) { _chart.type = _type; + dc.override(_chart, 'rescale', function () { _chart._rescale(); _barWidth = undefined; @@ -92,9 +93,10 @@ dc.barChart = function (parent, chartGroup) { function getCharts() { - if (parent instanceof Object) { - if (parent.children() instanceof Array) { - return parent.children().filter(function (chart) { + if (dc.instanceOfChart(parent) && typeof parent.children === 'function') { + var children = parent.children(); + if (children instanceof Array) { + return children.filter(function (chart) { return chart.type === _type; }); }