@@ -13,7 +13,7 @@ var isNumeric = require('fast-isnumeric');
13
13
14
14
var Registry = require ( '../../registry' ) ;
15
15
var Axes = require ( '../../plots/cartesian/axes' ) ;
16
- var Lib = require ( '../../lib ' ) ;
16
+ var Sieve = require ( './sieve.js ' ) ;
17
17
18
18
/*
19
19
* Bar chart stacking/grouping positioning and autoscaling calculations
@@ -52,24 +52,44 @@ module.exports = function setPositions(gd, plotinfo) {
52
52
function setGroupPositions ( gd , pa , sa , traces ) {
53
53
if ( ! traces . length ) return ;
54
54
55
- if ( gd . _fullLayout . barmode === 'overlay' ) {
55
+ var barmode = gd . _fullLayout . barmode ,
56
+ overlay = ( barmode === 'overlay' ) ,
57
+ group = ( barmode === 'group' ) ;
58
+
59
+ if ( overlay ) {
56
60
setGroupPositionsInOverlayMode ( gd , pa , sa , traces ) ;
57
61
}
62
+ else if ( group ) {
63
+ setGroupPositionsInGroupMode ( gd , pa , sa , traces ) ;
64
+ }
58
65
else {
59
- setOffsetAndWidth ( gd , pa , traces ) ;
60
- setBaseAndSize ( gd , sa , traces ) ;
66
+ setGroupPositionsInStackOrRelativeMode ( gd , pa , sa , traces ) ;
61
67
}
62
68
}
63
69
64
70
65
71
function setGroupPositionsInOverlayMode ( gd , pa , sa , traces ) {
66
- // set bar offsets and widths
72
+ var barnorm = gd . _fullLayout . barnorm ,
73
+ separateNegativeValues = false ,
74
+ dontMergeOverlappingData = ! barnorm ;
75
+
76
+ // update position axis and set bar offsets and widths
67
77
traces . forEach ( function ( trace ) {
68
- setOffsetAndWidth ( gd , pa , [ trace ] ) ;
78
+ var sieve = new Sieve (
79
+ [ trace ] , separateNegativeValues , dontMergeOverlappingData
80
+ ) ,
81
+ minDiff = sieve . minDiff ,
82
+ distinctPositions = sieve . distinctPositions ;
83
+
84
+ setOffsetAndWidth ( gd , pa , sieve ) ;
85
+
86
+ Axes . minDtick ( pa , minDiff , distinctPositions [ 0 ] ) ;
87
+ Axes . expand ( pa , distinctPositions , { vpad : minDiff / 2 } ) ;
69
88
} ) ;
70
89
71
- // for overlaid bars,
72
- // just make sure the size axis includes zero,
90
+ // update size axis and set bar bases and sizes
91
+ //
92
+ // make sure the size axis includes zero,
73
93
// along with the tops of each bar,
74
94
// and store these bar tops in calcdata
75
95
var sLetter = getAxisLetter ( sa ) ,
@@ -81,53 +101,112 @@ function setGroupPositionsInOverlayMode(gd, pa, sa, traces) {
81
101
}
82
102
83
103
84
- // bar position offset and width calculation
85
- // traces is a list of traces (in calcdata) to look at together
86
- // to find the maximum width bars that won't overlap
87
- // for stacked or grouped bars, this is all vertical or horizontal
88
- // bars for overlaid bars, call this individually on each trace.
89
- function setOffsetAndWidth ( gd , pa , traces ) {
104
+ function setGroupPositionsInGroupMode ( gd , pa , sa , traces ) {
90
105
var fullLayout = gd . _fullLayout ,
91
- pLetter = getAxisLetter ( pa ) ,
92
- i , trace ,
93
- j , bar ;
106
+ barnorm = fullLayout . barnorm ,
107
+ separateNegativeValues = false ,
108
+ dontMergeOverlappingData = ! barnorm ,
109
+ sieve = new Sieve (
110
+ traces , separateNegativeValues , dontMergeOverlappingData
111
+ ) ,
112
+ minDiff = sieve . minDiff ,
113
+ distinctPositions = sieve . distinctPositions ;
94
114
95
- // make list of bar positions
96
- var positions = [ ] ;
97
- for ( i = 0 ; i < traces . length ; i ++ ) {
98
- trace = traces [ i ] ;
99
- for ( j = 0 ; j < trace . length ; j ++ ) {
100
- bar = trace [ j ] ;
101
- positions . push ( bar . p ) ;
102
- }
103
- }
115
+ // set bar offsets and widths
116
+ setOffsetAndWidthInGroupMode ( gd , pa , sieve ) ;
104
117
105
- var dv = Lib . distinctVals ( positions ) ,
106
- distinctPositions = dv . vals ,
107
- minDiff = dv . minDiff ;
118
+ // update position axis
119
+ Axes . minDtick ( pa , minDiff , distinctPositions [ 0 ] ) ;
120
+ Axes . expand ( pa , distinctPositions , { vpad : minDiff / 2 } ) ;
108
121
109
- // check if there are any overlapping positions;
110
- // if there aren't, let them have full width even if mode is group
111
- var overlap = false ;
112
- if ( fullLayout . barmode === 'group' ) {
113
- overlap = ( positions . length !== distinctPositions . length ) ;
114
- }
122
+ // set bar bases and sizes
123
+ setBaseAndSize ( gd , sa , sieve ) ;
124
+ }
125
+
126
+
127
+ function setGroupPositionsInStackOrRelativeMode ( gd , pa , sa , traces ) {
128
+ var fullLayout = gd . _fullLayout ,
129
+ barmode = fullLayout . barmode ,
130
+ stack = ( barmode === 'stack' ) ,
131
+ relative = ( barmode === 'relative' ) ,
132
+ barnorm = gd . _fullLayout . barnorm ,
133
+ separateNegativeValues = relative ,
134
+ dontMergeOverlappingData = ! ( barnorm || stack || relative ) ,
135
+ sieve = new Sieve (
136
+ traces , separateNegativeValues , dontMergeOverlappingData
137
+ ) ,
138
+ minDiff = sieve . minDiff ,
139
+ distinctPositions = sieve . distinctPositions ;
115
140
116
- // check forced minimum dtick
117
- Axes . minDtick ( pa , minDiff , distinctPositions [ 0 ] , overlap ) ;
141
+ // set bar offsets and widths
142
+ setOffsetAndWidth ( gd , pa , sieve ) ;
118
143
119
- // position axis autorange - always tight fitting
144
+ // update position axis
145
+ Axes . minDtick ( pa , minDiff , distinctPositions [ 0 ] ) ;
120
146
Axes . expand ( pa , distinctPositions , { vpad : minDiff / 2 } ) ;
121
147
122
- // computer bar widths and position offsets
123
- var barGroupWidth = minDiff * ( 1 - fullLayout . bargap ) ,
148
+ // set bar bases and sizes
149
+ setBaseAndSize ( gd , sa , sieve ) ;
150
+ }
151
+
152
+
153
+ function setOffsetAndWidth ( gd , pa , sieve ) {
154
+ var fullLayout = gd . _fullLayout ,
155
+ pLetter = getAxisLetter ( pa ) ,
156
+ traces = sieve . traces ,
157
+ bargap = fullLayout . bargap ,
158
+ bargroupgap = fullLayout . bargroupgap ,
159
+ minDiff = sieve . minDiff ;
160
+
161
+ // set bar offsets and widths
162
+ var barGroupWidth = minDiff * ( 1 - bargap ) ,
163
+ barWidthPlusGap = barGroupWidth ,
164
+ barWidth = barWidthPlusGap * ( 1 - bargroupgap ) ;
165
+
166
+ // computer bar group center and bar offset
167
+ var offsetFromCenter = - barWidth / 2 ,
168
+ barCenter = 0 ;
169
+
170
+ for ( var i = 0 ; i < traces . length ; i ++ ) {
171
+ var trace = traces [ i ] ;
172
+
173
+ // store bar width and offset for this trace
174
+ var t = trace [ 0 ] . t ;
175
+ t . barwidth = barWidth ;
176
+ t . poffset = offsetFromCenter ;
177
+ t . bargroupwidth = barGroupWidth ;
178
+
179
+ // store the bar center in each calcdata item
180
+ for ( var j = 0 ; j < trace . length ; j ++ ) {
181
+ var bar = trace [ j ] ;
182
+ bar [ pLetter ] = bar . p + barCenter ;
183
+ }
184
+ }
185
+ }
186
+
187
+
188
+ function setOffsetAndWidthInGroupMode ( gd , pa , sieve ) {
189
+ var fullLayout = gd . _fullLayout ,
190
+ pLetter = getAxisLetter ( pa ) ,
191
+ traces = sieve . traces ,
192
+ bargap = fullLayout . bargap ,
193
+ bargroupgap = fullLayout . bargroupgap ,
194
+ positions = sieve . positions ,
195
+ distinctPositions = sieve . distinctPositions ,
196
+ minDiff = sieve . minDiff ;
197
+
198
+ // if there aren't any overlapping positions,
199
+ // let them have full width even if mode is group
200
+ var overlap = ( positions . length !== distinctPositions . length ) ;
201
+
202
+ var barGroupWidth = minDiff * ( 1 - bargap ) ,
124
203
barWidthPlusGap = ( overlap ) ?
125
204
barGroupWidth / traces . length :
126
205
barGroupWidth ,
127
- barWidth = barWidthPlusGap * ( 1 - fullLayout . bargroupgap ) ;
206
+ barWidth = barWidthPlusGap * ( 1 - bargroupgap ) ;
128
207
129
- for ( i = 0 ; i < traces . length ; i ++ ) {
130
- trace = traces [ i ] ;
208
+ for ( var i = 0 ; i < traces . length ; i ++ ) {
209
+ var trace = traces [ i ] ;
131
210
132
211
// computer bar group center and bar offset
133
212
var offsetFromCenter = ( overlap ) ?
@@ -142,17 +221,18 @@ function setOffsetAndWidth(gd, pa, traces) {
142
221
t . bargroupwidth = barGroupWidth ;
143
222
144
223
// store the bar center in each calcdata item
145
- for ( j = 0 ; j < trace . length ; j ++ ) {
146
- bar = trace [ j ] ;
224
+ for ( var j = 0 ; j < trace . length ; j ++ ) {
225
+ var bar = trace [ j ] ;
147
226
bar [ pLetter ] = bar . p + barCenter ;
148
227
}
149
228
}
150
229
}
151
230
152
231
153
- function setBaseAndSize ( gd , sa , traces ) {
232
+ function setBaseAndSize ( gd , sa , sieve ) {
154
233
var fullLayout = gd . _fullLayout ,
155
234
sLetter = getAxisLetter ( sa ) ,
235
+ traces = sieve . traces ,
156
236
i , trace ,
157
237
j , bar ;
158
238
0 commit comments