@@ -116,10 +116,11 @@ module.exports = function setPositions(gd, plotinfo) {
116116 else barposition ( bl ) ;
117117
118118 var stack = ( fullLayout . barmode === 'stack' ) ,
119+ relative = ( fullLayout . barmode === 'relative' ) ,
119120 norm = fullLayout . barnorm ;
120121
121122 // bar size range and stacking calculation
122- if ( stack || norm ) {
123+ if ( stack || relative || norm ) {
123124 // for stacked bars, we need to evaluate every step in every
124125 // stack, because negative bars mean the extremes could be
125126 // anywhere
@@ -142,13 +143,15 @@ module.exports = function setPositions(gd, plotinfo) {
142143 ti = gd . calcdata [ bl [ i ] ] ;
143144 for ( j = 0 ; j < ti . length ; j ++ ) {
144145 sv = Math . round ( ti [ j ] . p / sumround ) ;
146+ // store the negative sum value for p at the same key, with sign flipped
147+ if ( relative && ti [ j ] . s < 0 ) sv = - Math . round ( ti [ j ] . p / sumround ) ;
145148 var previousSum = sums [ sv ] || 0 ;
146- if ( stack ) ti [ j ] . b = previousSum ;
149+ if ( stack || relative ) ti [ j ] . b = previousSum ;
147150 barEnd = ti [ j ] . b + ti [ j ] . s ;
148151 sums [ sv ] = previousSum + ti [ j ] . s ;
149152
150153 // store the bar top in each calcdata item
151- if ( stack ) {
154+ if ( stack || relative ) {
152155 ti [ j ] [ sLetter ] = barEnd ;
153156 if ( ! norm && isNumeric ( sa . c2l ( barEnd ) ) ) {
154157 sMax = Math . max ( sMax , barEnd ) ;
@@ -161,13 +164,18 @@ module.exports = function setPositions(gd, plotinfo) {
161164 if ( norm ) {
162165 padded = false ;
163166 var top = norm === 'fraction' ? 1 : 100 ,
167+ isNegative = false ,
164168 tiny = top / 1e9 ; // in case of rounding error in sum
165169 sMin = 0 ;
166170 sMax = stack ? top : 0 ;
167171 for ( i = 0 ; i < bl . length ; i ++ ) { // trace index
168172 ti = gd . calcdata [ bl [ i ] ] ;
169173 for ( j = 0 ; j < ti . length ; j ++ ) {
170- scale = top / sums [ Math . round ( ti [ j ] . p / sumround ) ] ;
174+ relAndNegative = relative && ti [ j ] . s < 0 ;
175+ sv = Math . round ( ti [ j ] . p / sumround ) ;
176+ if ( relAndNegative ) sv = - Math . round ( ti [ j ] . p / sumround ) ; // locate negative sum amount for this p val
177+ scale = top / sums [ sv ] ;
178+ if ( relAndNegative ) scale *= - 1 ; // preserve sign if negative
171179 ti [ j ] . b *= scale ;
172180 ti [ j ] . s *= scale ;
173181 barEnd = ti [ j ] . b + ti [ j ] . s ;
0 commit comments