@@ -19,6 +19,7 @@ var svgTextUtils = require('../../lib/svg_text_utils');
1919var Color = require ( '../../components/color' ) ;
2020var Drawing = require ( '../../components/drawing' ) ;
2121var Registry = require ( '../../registry' ) ;
22+ var makeTraceGroups = require ( '../../plots/cartesian/make_trace_groups' ) ;
2223
2324var attributes = require ( './attributes' ) ,
2425 attributeText = attributes . text ,
@@ -31,138 +32,128 @@ var attributes = require('./attributes'),
3132var TEXTPAD = 3 ;
3233
3334module . exports = function plot ( gd , plotinfo , cdbar , barLayer ) {
35+ var bartraces = makeTraceGroups ( gd , plotinfo , cdbar , barLayer , 'trace bars' , plotOne ) ;
36+
37+ // error bars are on the top
38+ Registry . getComponentMethod ( 'errorbars' , 'plot' ) ( bartraces , plotinfo ) ;
39+ } ;
40+
41+ function plotOne ( gd , plotinfo , cd , plotGroup ) {
3442 var xa = plotinfo . xaxis ;
3543 var ya = plotinfo . yaxis ;
3644 var fullLayout = gd . _fullLayout ;
45+ var cd0 = cd [ 0 ] ;
46+ var t = cd0 . t ;
47+ var trace = cd0 . trace ;
3748
38- var bartraces = barLayer . selectAll ( 'g.trace.bars' )
39- . data ( cdbar , function ( d ) { return d [ 0 ] . trace . uid ; } ) ;
40-
41- bartraces . enter ( ) . append ( 'g' )
42- . attr ( 'class' , 'trace bars' )
43- . append ( 'g' )
44- . attr ( 'class' , 'points' ) ;
45-
46- bartraces . exit ( ) . remove ( ) ;
47-
48- bartraces . order ( ) ;
49+ if ( ! plotinfo . isRangePlot ) cd0 . node3 = plotGroup ;
4950
50- bartraces . each ( function ( d ) {
51- var cd0 = d [ 0 ] ;
52- var t = cd0 . t ;
53- var trace = cd0 . trace ;
54- var sel = d3 . select ( this ) ;
51+ var poffset = t . poffset ;
52+ var poffsetIsArray = Array . isArray ( poffset ) ;
5553
56- if ( ! plotinfo . isRangePlot ) cd0 . node3 = sel ;
54+ var pointGroup = Lib . ensureSingle ( plotGroup , 'g' , 'points' ) ;
5755
58- var poffset = t . poffset ;
59- var poffsetIsArray = Array . isArray ( poffset ) ;
56+ var bars = pointGroup . selectAll ( 'g.point' ) . data ( Lib . identity ) ;
6057
61- var bars = sel . select ( 'g.points' ) . selectAll ( 'g.point' ) . data ( Lib . identity ) ;
58+ bars . enter ( ) . append ( 'g' )
59+ . classed ( 'point' , true ) ;
6260
63- bars . enter ( ) . append ( 'g' )
64- . classed ( 'point' , true ) ;
61+ bars . exit ( ) . remove ( ) ;
6562
66- bars . exit ( ) . remove ( ) ;
63+ bars . each ( function ( di , i ) {
64+ var bar = d3 . select ( this ) ;
6765
68- bars . each ( function ( di , i ) {
69- var bar = d3 . select ( this ) ;
66+ // now display the bar
67+ // clipped xf/yf (2nd arg true): non-positive
68+ // log values go off-screen by plotwidth
69+ // so you see them continue if you drag the plot
70+ var p0 = di . p + ( ( poffsetIsArray ) ? poffset [ i ] : poffset ) ,
71+ p1 = p0 + di . w ,
72+ s0 = di . b ,
73+ s1 = s0 + di . s ;
7074
71- // now display the bar
72- // clipped xf/yf (2nd arg true): non-positive
73- // log values go off-screen by plotwidth
74- // so you see them continue if you drag the plot
75- var p0 = di . p + ( ( poffsetIsArray ) ? poffset [ i ] : poffset ) ,
76- p1 = p0 + di . w ,
77- s0 = di . b ,
78- s1 = s0 + di . s ;
75+ var x0 , x1 , y0 , y1 ;
76+ if ( trace . orientation === 'h' ) {
77+ y0 = ya . c2p ( p0 , true ) ;
78+ y1 = ya . c2p ( p1 , true ) ;
79+ x0 = xa . c2p ( s0 , true ) ;
80+ x1 = xa . c2p ( s1 , true ) ;
7981
80- var x0 , x1 , y0 , y1 ;
81- if ( trace . orientation === 'h' ) {
82- y0 = ya . c2p ( p0 , true ) ;
83- y1 = ya . c2p ( p1 , true ) ;
84- x0 = xa . c2p ( s0 , true ) ;
85- x1 = xa . c2p ( s1 , true ) ;
86-
87- // for selections
88- di . ct = [ x1 , ( y0 + y1 ) / 2 ] ;
89- }
90- else {
91- x0 = xa . c2p ( p0 , true ) ;
92- x1 = xa . c2p ( p1 , true ) ;
93- y0 = ya . c2p ( s0 , true ) ;
94- y1 = ya . c2p ( s1 , true ) ;
95-
96- // for selections
97- di . ct = [ ( x0 + x1 ) / 2 , y1 ] ;
98- }
82+ // for selections
83+ di . ct = [ x1 , ( y0 + y1 ) / 2 ] ;
84+ }
85+ else {
86+ x0 = xa . c2p ( p0 , true ) ;
87+ x1 = xa . c2p ( p1 , true ) ;
88+ y0 = ya . c2p ( s0 , true ) ;
89+ y1 = ya . c2p ( s1 , true ) ;
9990
100- if ( ! isNumeric ( x0 ) || ! isNumeric ( x1 ) ||
101- ! isNumeric ( y0 ) || ! isNumeric ( y1 ) ||
102- x0 === x1 || y0 === y1 ) {
103- bar . remove ( ) ;
104- return ;
105- }
91+ // for selections
92+ di . ct = [ ( x0 + x1 ) / 2 , y1 ] ;
93+ }
10694
107- var lw = ( di . mlw + 1 || trace . marker . line . width + 1 ||
108- ( di . trace ? di . trace . marker . line . width : 0 ) + 1 ) - 1 ,
109- offset = d3 . round ( ( lw / 2 ) % 1 , 2 ) ;
95+ if ( ! isNumeric ( x0 ) || ! isNumeric ( x1 ) ||
96+ ! isNumeric ( y0 ) || ! isNumeric ( y1 ) ||
97+ x0 === x1 || y0 === y1 ) {
98+ bar . remove ( ) ;
99+ return ;
100+ }
110101
111- function roundWithLine ( v ) {
112- // if there are explicit gaps, don't round,
113- // it can make the gaps look crappy
114- return ( fullLayout . bargap === 0 && fullLayout . bargroupgap === 0 ) ?
115- d3 . round ( Math . round ( v ) - offset , 2 ) : v ;
116- }
102+ var lw = ( di . mlw + 1 || trace . marker . line . width + 1 ||
103+ ( di . trace ? di . trace . marker . line . width : 0 ) + 1 ) - 1 ,
104+ offset = d3 . round ( ( lw / 2 ) % 1 , 2 ) ;
117105
118- function expandToVisible ( v , vc ) {
119- // if it's not in danger of disappearing entirely,
120- // round more precisely
121- return Math . abs ( v - vc ) >= 2 ? roundWithLine ( v ) :
122- // but if it's very thin, expand it so it's
123- // necessarily visible, even if it might overlap
124- // its neighbor
125- ( v > vc ? Math . ceil ( v ) : Math . floor ( v ) ) ;
126- }
106+ function roundWithLine ( v ) {
107+ // if there are explicit gaps, don't round,
108+ // it can make the gaps look crappy
109+ return ( fullLayout . bargap === 0 && fullLayout . bargroupgap === 0 ) ?
110+ d3 . round ( Math . round ( v ) - offset , 2 ) : v ;
111+ }
127112
128- if ( ! gd . _context . staticPlot ) {
129- // if bars are not fully opaque or they have a line
130- // around them, round to integer pixels, mainly for
131- // safari so we prevent overlaps from its expansive
132- // pixelation. if the bars ARE fully opaque and have
133- // no line, expand to a full pixel to make sure we
134- // can see them
135- var op = Color . opacity ( di . mc || trace . marker . color ) ,
136- fixpx = ( op < 1 || lw > 0.01 ) ?
137- roundWithLine : expandToVisible ;
138- x0 = fixpx ( x0 , x1 ) ;
139- x1 = fixpx ( x1 , x0 ) ;
140- y0 = fixpx ( y0 , y1 ) ;
141- y1 = fixpx ( y1 , y0 ) ;
142- }
113+ function expandToVisible ( v , vc ) {
114+ // if it's not in danger of disappearing entirely,
115+ // round more precisely
116+ return Math . abs ( v - vc ) >= 2 ? roundWithLine ( v ) :
117+ // but if it's very thin, expand it so it's
118+ // necessarily visible, even if it might overlap
119+ // its neighbor
120+ ( v > vc ? Math . ceil ( v ) : Math . floor ( v ) ) ;
121+ }
143122
144- Lib . ensureSingle ( bar , 'path' )
145- . style ( 'vector-effect' , 'non-scaling-stroke' )
146- . attr ( 'd' ,
147- 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z' )
148- . call ( Drawing . setClipUrl , plotinfo . layerClipId ) ;
123+ if ( ! gd . _context . staticPlot ) {
124+ // if bars are not fully opaque or they have a line
125+ // around them, round to integer pixels, mainly for
126+ // safari so we prevent overlaps from its expansive
127+ // pixelation. if the bars ARE fully opaque and have
128+ // no line, expand to a full pixel to make sure we
129+ // can see them
130+ var op = Color . opacity ( di . mc || trace . marker . color ) ,
131+ fixpx = ( op < 1 || lw > 0.01 ) ?
132+ roundWithLine : expandToVisible ;
133+ x0 = fixpx ( x0 , x1 ) ;
134+ x1 = fixpx ( x1 , x0 ) ;
135+ y0 = fixpx ( y0 , y1 ) ;
136+ y1 = fixpx ( y1 , y0 ) ;
137+ }
149138
150- appendBarText ( gd , bar , d , i , x0 , x1 , y0 , y1 ) ;
139+ Lib . ensureSingle ( bar , 'path' )
140+ . style ( 'vector-effect' , 'non-scaling-stroke' )
141+ . attr ( 'd' ,
142+ 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z' )
143+ . call ( Drawing . setClipUrl , plotinfo . layerClipId ) ;
151144
152- if ( plotinfo . layerClipId ) {
153- Drawing . hideOutsideRangePoint ( d [ i ] , bar . select ( 'text' ) , xa , ya , trace . xcalendar , trace . ycalendar ) ;
154- }
155- } ) ;
145+ appendBarText ( gd , bar , cd , i , x0 , x1 , y0 , y1 ) ;
156146
157- // lastly, clip points groups of `cliponaxis !== false` traces
158- // on `plotinfo._hasClipOnAxisFalse === true` subplots
159- var hasClipOnAxisFalse = d [ 0 ] . trace . cliponaxis === false ;
160- Drawing . setClipUrl ( sel , hasClipOnAxisFalse ? null : plotinfo . layerClipId ) ;
147+ if ( plotinfo . layerClipId ) {
148+ Drawing . hideOutsideRangePoint ( di , bar . select ( 'text' ) , xa , ya , trace . xcalendar , trace . ycalendar ) ;
149+ }
161150 } ) ;
162151
163- // error bars are on the top
164- Registry . getComponentMethod ( 'errorbars' , 'plot' ) ( bartraces , plotinfo ) ;
165- } ;
152+ // lastly, clip points groups of `cliponaxis !== false` traces
153+ // on `plotinfo._hasClipOnAxisFalse === true` subplots
154+ var hasClipOnAxisFalse = cd0 . trace . cliponaxis === false ;
155+ Drawing . setClipUrl ( plotGroup , hasClipOnAxisFalse ? null : plotinfo . layerClipId ) ;
156+ }
166157
167158function appendBarText ( gd , bar , calcTrace , i , x0 , x1 , y0 , y1 ) {
168159 var textPosition ;
0 commit comments