27
27
dc . barChart = function ( parent , chartGroup ) {
28
28
var MIN_BAR_WIDTH = 1 ;
29
29
var DEFAULT_GAP_BETWEEN_BARS = 2 ;
30
+ var DEFAULT_GAP_BETWEEN_BAR_SERIES = 5 ;
30
31
var LABEL_PADDING = 3 ;
32
+ var _type = "dc.BAR_CHART" ;
31
33
32
34
var _chart = dc . stackMixin ( dc . coordinateGridMixin ( { } ) ) ;
33
35
34
36
var _gap = DEFAULT_GAP_BETWEEN_BARS ;
37
+ var _serieGap = DEFAULT_GAP_BETWEEN_BAR_SERIES ;
35
38
var _centerBar = false ;
36
39
var _alwaysUseRounding = false ;
37
40
38
41
var _barWidth ;
39
42
43
+
44
+ _chart . type = _type ;
40
45
dc . override ( _chart , 'rescale' , function ( ) {
41
46
_chart . _rescale ( ) ;
42
47
_barWidth = undefined ;
@@ -46,7 +51,7 @@ dc.barChart = function (parent, chartGroup) {
46
51
dc . override ( _chart , 'render' , function ( ) {
47
52
if ( _chart . round ( ) && _centerBar && ! _alwaysUseRounding ) {
48
53
dc . logger . warn ( 'By default, brush rounding is disabled if bars are centered. ' +
49
- 'See dc.js bar chart API documentation for details.' ) ;
54
+ 'See dc.js bar chart API documentation for details.' ) ;
50
55
}
51
56
52
57
return _chart . _render ( ) ;
@@ -81,11 +86,24 @@ dc.barChart = function (parent, chartGroup) {
81
86
} ) ;
82
87
} ;
83
88
84
- function barHeight ( d ) {
89
+ function barHeight ( d ) {
85
90
return dc . utils . safeNumber ( Math . abs ( _chart . y ( ) ( d . y + d . y0 ) - _chart . y ( ) ( d . y0 ) ) ) ;
86
91
}
87
92
88
- function renderLabels ( layer , layerIndex , d ) {
93
+
94
+ function getCharts ( ) {
95
+ if ( parent instanceof Object ) {
96
+ if ( parent . children ( ) instanceof Array ) {
97
+ return parent . children ( ) . filter ( function ( chart ) {
98
+ return chart . type === _type ;
99
+ } ) ;
100
+ }
101
+ }
102
+ return [ ] ;
103
+
104
+ }
105
+
106
+ function renderLabels ( layer , layerIndex , d ) {
89
107
var labels = layer . selectAll ( 'text.barLabel' )
90
108
. data ( d . values , dc . pluck ( 'x' ) ) ;
91
109
@@ -102,8 +120,19 @@ dc.barChart = function (parent, chartGroup) {
102
120
dc . transition ( labels , _chart . transitionDuration ( ) , _chart . transitionDelay ( ) )
103
121
. attr ( 'x' , function ( d ) {
104
122
var x = _chart . x ( ) ( d . x ) ;
105
- if ( ! _centerBar ) {
106
- x += _barWidth / 2 ;
123
+ var charts = getCharts ( ) ;
124
+ if ( charts . length > 1 ) {
125
+ x += _chart . serieGap ( ) / 2 ;
126
+ x += layerIndex * ( _barWidth + _gap ) ;
127
+ x += _gap / 2 ;
128
+ }
129
+ x += _barWidth / 2 ;
130
+ if ( _centerBar && ! _chart . isOrdinal ( ) ) {
131
+ if ( charts . length > 1 ) {
132
+ x -= ( ( _barWidth + _gap ) * charts . length + _chart . serieGap ( ) ) / 2 ;
133
+ } else {
134
+ x -= _barWidth / 2 ;
135
+ }
107
136
}
108
137
return dc . utils . safeNumber ( x ) ;
109
138
} )
@@ -125,7 +154,7 @@ dc.barChart = function (parent, chartGroup) {
125
154
. remove ( ) ;
126
155
}
127
156
128
- function renderBars ( layer , layerIndex , d ) {
157
+ function renderBars ( layer , layerIndex , d ) {
129
158
var bars = layer . selectAll ( 'rect.bar' )
130
159
. data ( d . values , dc . pluck ( 'x' ) ) ;
131
160
@@ -147,8 +176,19 @@ dc.barChart = function (parent, chartGroup) {
147
176
dc . transition ( bars , _chart . transitionDuration ( ) , _chart . transitionDelay ( ) )
148
177
. attr ( 'x' , function ( d ) {
149
178
var x = _chart . x ( ) ( d . x ) ;
150
- if ( _centerBar ) {
151
- x -= _barWidth / 2 ;
179
+ var charts = getCharts ( ) ;
180
+ var chartIndex = charts . indexOf ( _chart ) ;
181
+ if ( charts . length > 1 ) {
182
+ x += _chart . serieGap ( ) / 2 ;
183
+ x += chartIndex * ( _barWidth + _gap ) ;
184
+ x += _gap / 2 ;
185
+ }
186
+ if ( _centerBar && ! _chart . isOrdinal ( ) ) {
187
+ if ( charts . length > 1 ) {
188
+ x -= ( ( _barWidth + _gap ) * charts . length + _chart . serieGap ( ) ) / 2 ;
189
+ } else {
190
+ x -= _barWidth / 2 ;
191
+ }
152
192
}
153
193
if ( _chart . isOrdinal ( ) && _gap !== undefined ) {
154
194
x += _gap / 2 ;
@@ -177,19 +217,31 @@ dc.barChart = function (parent, chartGroup) {
177
217
. remove ( ) ;
178
218
}
179
219
180
- function calculateBarWidth ( ) {
220
+ function calculateBarWidth ( ) {
181
221
if ( _barWidth === undefined ) {
182
222
var numberOfBars = _chart . xUnitCount ( ) ;
183
-
184
- // please can't we always use rangeBands for bar charts?
185
- if ( _chart . isOrdinal ( ) && _gap === undefined ) {
186
- _barWidth = Math . floor ( _chart . x ( ) . rangeBand ( ) ) ;
187
- } else if ( _gap ) {
188
- _barWidth = Math . floor ( ( _chart . xAxisLength ( ) - ( numberOfBars - 1 ) * _gap ) / numberOfBars ) ;
223
+ var charts = getCharts ( ) ;
224
+ if ( charts . length > 1 ) {
225
+ var numberOfCharts = charts . length ;
226
+ if ( _chart . isOrdinal ( ) ) {
227
+ _barWidth = Math . floor ( ( _chart . x ( ) . rangeBand ( ) - _chart . serieGap ( ) ) / numberOfCharts - _gap ) ;
228
+ } else {
229
+ _barWidth = Math . floor ( ( _chart . xAxisLength ( ) - ( _chart . xUnitCount ( ) - 1 ) * _chart . serieGap ( ) -
230
+ ( numberOfBars - 1 ) * ( numberOfCharts ) * _gap ) / ( numberOfBars * numberOfCharts ) ) ;
231
+ }
189
232
} else {
190
- _barWidth = Math . floor ( _chart . xAxisLength ( ) / ( 1 + _chart . barPadding ( ) ) / numberOfBars ) ;
233
+ // please can't we always use rangeBands for bar charts?
234
+ if ( _chart . isOrdinal ( ) && _gap === undefined ) {
235
+ _barWidth = Math . floor ( _chart . x ( ) . rangeBand ( ) ) ;
236
+ } else if ( _gap ) {
237
+ _barWidth = Math . floor ( ( _chart . xAxisLength ( ) - ( numberOfBars - 1 ) * _gap ) / numberOfBars ) ;
238
+ } else {
239
+ _barWidth = Math . floor ( _chart . xAxisLength ( ) / ( 1 + _chart . barPadding ( ) ) / numberOfBars ) ;
240
+ }
191
241
}
192
242
243
+
244
+
193
245
if ( _barWidth === Infinity || isNaN ( _barWidth ) || _barWidth < MIN_BAR_WIDTH ) {
194
246
_barWidth = MIN_BAR_WIDTH ;
195
247
}
@@ -299,6 +351,24 @@ dc.barChart = function (parent, chartGroup) {
299
351
return _chart ;
300
352
} ;
301
353
354
+ /**
355
+ * Manually set fixed gap (in px) between bar groups instead of relying on the default auto-generated
356
+ * gap. Only applicable for grouped bar charts.
357
+ * @name serieGap
358
+ * @memberof dc.barChart
359
+ * @instance
360
+ * @param {Number } [serieGap=5]
361
+ * @return {Number }
362
+ * @return {dc.barChart }
363
+ */
364
+ _chart . serieGap = function ( serieGap ) {
365
+ if ( ! arguments . length ) {
366
+ return _serieGap ;
367
+ }
368
+ _serieGap = serieGap ;
369
+ return _chart ;
370
+ } ;
371
+
302
372
_chart . extendBrush = function ( ) {
303
373
var extent = _chart . brush ( ) . extent ( ) ;
304
374
if ( _chart . round ( ) && ( ! _centerBar || _alwaysUseRounding ) ) {
@@ -335,7 +405,7 @@ dc.barChart = function (parent, chartGroup) {
335
405
return _chart ;
336
406
} ;
337
407
338
- function colorFilter ( color , inv ) {
408
+ function colorFilter ( color , inv ) {
339
409
return function ( ) {
340
410
var item = d3 . select ( this ) ;
341
411
var match = item . attr ( 'fill' ) === color ;
0 commit comments