@@ -64,8 +64,8 @@ function plot(gd, plotinfo, cdbox) {
64
64
return ;
65
65
}
66
66
67
- // set axis via orientation
68
67
var posAxis , valAxis ;
68
+
69
69
if ( trace . orientation === 'h' ) {
70
70
posAxis = ya ;
71
71
valAxis = xa ;
@@ -77,91 +77,90 @@ function plot(gd, plotinfo, cdbox) {
77
77
// save the box size and box position for use by hover
78
78
t . bPos = bPos ;
79
79
t . bdPos = bdPos ;
80
+ t . wdPos = wdPos ;
80
81
81
82
// boxes and whiskers
82
- sel . selectAll ( 'path.box' )
83
- . data ( Lib . identity )
84
- . enter ( ) . append ( 'path' )
85
- . style ( 'vector-effect' , 'non-scaling-stroke' )
86
- . attr ( 'class' , 'box' )
87
- . each ( function ( d ) {
88
- var posc = posAxis . c2p ( d . pos + bPos , true ) ,
89
- pos0 = posAxis . c2p ( d . pos + bPos - bdPos , true ) ,
90
- pos1 = posAxis . c2p ( d . pos + bPos + bdPos , true ) ,
91
- posw0 = posAxis . c2p ( d . pos + bPos - wdPos , true ) ,
92
- posw1 = posAxis . c2p ( d . pos + bPos + wdPos , true ) ,
93
- q1 = valAxis . c2p ( d . q1 , true ) ,
94
- q3 = valAxis . c2p ( d . q3 , true ) ,
95
- // make sure median isn't identical to either of the
96
- // quartiles, so we can see it
97
- m = Lib . constrain ( valAxis . c2p ( d . med , true ) ,
98
- Math . min ( q1 , q3 ) + 1 , Math . max ( q1 , q3 ) - 1 ) ,
99
- lf = valAxis . c2p ( trace . boxpoints === false ? d . min : d . lf , true ) ,
100
- uf = valAxis . c2p ( trace . boxpoints === false ? d . max : d . uf , true ) ;
101
-
102
- if ( trace . orientation === 'h' ) {
103
- d3 . select ( this ) . attr ( 'd' ,
104
- 'M' + m + ',' + pos0 + 'V' + pos1 + // median line
105
- 'M' + q1 + ',' + pos0 + 'V' + pos1 + 'H' + q3 + 'V' + pos0 + 'Z' + // box
106
- 'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers
107
- ( ( trace . whiskerwidth === 0 ) ? '' : // whisker caps
108
- 'M' + lf + ',' + posw0 + 'V' + posw1 + 'M' + uf + ',' + posw0 + 'V' + posw1 ) ) ;
109
- } else {
110
- d3 . select ( this ) . attr ( 'd' ,
111
- 'M' + pos0 + ',' + m + 'H' + pos1 + // median line
112
- 'M' + pos0 + ',' + q1 + 'H' + pos1 + 'V' + q3 + 'H' + pos0 + 'Z' + // box
113
- 'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers
114
- ( ( trace . whiskerwidth === 0 ) ? '' : // whisker caps
115
- 'M' + posw0 + ',' + lf + 'H' + posw1 + 'M' + posw0 + ',' + uf + 'H' + posw1 ) ) ;
116
- }
117
- } ) ;
83
+ plotBoxAndWhiskers ( sel , { pos : posAxis , val : valAxis } , trace , t ) ;
118
84
119
85
// draw points, if desired
120
86
if ( trace . boxpoints ) {
121
- plotPoints ( sel , plotinfo , trace , t ) ;
87
+ plotPoints ( sel , { x : xa , y : ya } , trace , t ) ;
122
88
}
123
89
124
90
// draw mean (and stdev diamond) if desired
125
91
if ( trace . boxmean ) {
126
- sel . selectAll ( 'path.mean' )
127
- . data ( Lib . identity )
128
- . enter ( ) . append ( 'path' )
129
- . attr ( 'class' , 'mean' )
130
- . style ( {
131
- fill : 'none' ,
132
- 'vector-effect' : 'non-scaling-stroke'
133
- } )
134
- . each ( function ( d ) {
135
- var posc = posAxis . c2p ( d . pos + bPos , true ) ,
136
- pos0 = posAxis . c2p ( d . pos + bPos - bdPos , true ) ,
137
- pos1 = posAxis . c2p ( d . pos + bPos + bdPos , true ) ,
138
- m = valAxis . c2p ( d . mean , true ) ,
139
- sl = valAxis . c2p ( d . mean - d . sd , true ) ,
140
- sh = valAxis . c2p ( d . mean + d . sd , true ) ;
141
- if ( trace . orientation === 'h' ) {
142
- d3 . select ( this ) . attr ( 'd' ,
143
- 'M' + m + ',' + pos0 + 'V' + pos1 +
144
- ( ( trace . boxmean !== 'sd' ) ? '' :
145
- 'm0,0L' + sl + ',' + posc + 'L' + m + ',' + pos0 + 'L' + sh + ',' + posc + 'Z' ) ) ;
146
- }
147
- else {
148
- d3 . select ( this ) . attr ( 'd' ,
149
- 'M' + pos0 + ',' + m + 'H' + pos1 +
150
- ( ( trace . boxmean !== 'sd' ) ? '' :
151
- 'm0,0L' + posc + ',' + sl + 'L' + pos0 + ',' + m + 'L' + posc + ',' + sh + 'Z' ) ) ;
152
- }
153
- } ) ;
92
+ plotBoxMean ( sel , { pos : posAxis , val : valAxis } , trace , t ) ;
154
93
}
155
94
} ) ;
156
95
}
157
96
158
- function plotPoints ( sel , plotinfo , trace , t ) {
159
- var xa = plotinfo . xaxis ;
160
- var ya = plotinfo . yaxis ;
97
+ function plotBoxAndWhiskers ( sel , axes , trace , t ) {
98
+ var posAxis = axes . pos ;
99
+ var valAxis = axes . val ;
100
+ var bPos = t . bPos ;
101
+ var wdPos = t . wdPos || 0 ;
102
+ var bPosPxOffset = t . bPosPxOffset || 0 ;
103
+ var whiskerWidth = trace . whiskerwidth || 0 ;
104
+
105
+ // to support for one-sided box
106
+ var bdPos0 ;
107
+ var bdPos1 ;
108
+ if ( Array . isArray ( t . bdPos ) ) {
109
+ bdPos0 = t . bdPos [ 0 ] ;
110
+ bdPos1 = t . bdPos [ 1 ] ;
111
+ } else {
112
+ bdPos0 = t . bdPos ;
113
+ bdPos1 = t . bdPos ;
114
+ }
115
+
116
+ sel . selectAll ( 'path.box' )
117
+ . data ( Lib . identity )
118
+ . enter ( ) . append ( 'path' )
119
+ . style ( 'vector-effect' , 'non-scaling-stroke' )
120
+ . attr ( 'class' , 'box' )
121
+ . each ( function ( d ) {
122
+ var pos = d . pos ;
123
+ var posc = posAxis . c2p ( pos + bPos , true ) + bPosPxOffset ;
124
+ var pos0 = posAxis . c2p ( pos + bPos - bdPos0 , true ) + bPosPxOffset ;
125
+ var pos1 = posAxis . c2p ( pos + bPos + bdPos1 , true ) + bPosPxOffset ;
126
+ var posw0 = posAxis . c2p ( pos + bPos - wdPos , true ) + bPosPxOffset ;
127
+ var posw1 = posAxis . c2p ( pos + bPos + wdPos , true ) + bPosPxOffset ;
128
+ var q1 = valAxis . c2p ( d . q1 , true ) ;
129
+ var q3 = valAxis . c2p ( d . q3 , true ) ;
130
+ // make sure median isn't identical to either of the
131
+ // quartiles, so we can see it
132
+ var m = Lib . constrain (
133
+ valAxis . c2p ( d . med , true ) ,
134
+ Math . min ( q1 , q3 ) + 1 , Math . max ( q1 , q3 ) - 1
135
+ ) ;
136
+ var lf = valAxis . c2p ( trace . boxpoints === false ? d . min : d . lf , true ) ;
137
+ var uf = valAxis . c2p ( trace . boxpoints === false ? d . max : d . uf , true ) ;
138
+
139
+ if ( trace . orientation === 'h' ) {
140
+ d3 . select ( this ) . attr ( 'd' ,
141
+ 'M' + m + ',' + pos0 + 'V' + pos1 + // median line
142
+ 'M' + q1 + ',' + pos0 + 'V' + pos1 + 'H' + q3 + 'V' + pos0 + 'Z' + // box
143
+ 'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers
144
+ ( ( whiskerWidth === 0 ) ? '' : // whisker caps
145
+ 'M' + lf + ',' + posw0 + 'V' + posw1 + 'M' + uf + ',' + posw0 + 'V' + posw1 ) ) ;
146
+ } else {
147
+ d3 . select ( this ) . attr ( 'd' ,
148
+ 'M' + pos0 + ',' + m + 'H' + pos1 + // median line
149
+ 'M' + pos0 + ',' + q1 + 'H' + pos1 + 'V' + q3 + 'H' + pos0 + 'Z' + // box
150
+ 'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers
151
+ ( ( whiskerWidth === 0 ) ? '' : // whisker caps
152
+ 'M' + posw0 + ',' + lf + 'H' + posw1 + 'M' + posw0 + ',' + uf + 'H' + posw1 ) ) ;
153
+ }
154
+ } ) ;
155
+ }
156
+
157
+ function plotPoints ( sel , axes , trace , t ) {
158
+ var xa = axes . x ;
159
+ var ya = axes . y ;
161
160
var bdPos = t . bdPos ;
162
161
var bPos = t . bPos ;
163
162
164
- // TODO ... unfortunately
163
+ // to support violin innerbox
165
164
var mode = trace . boxpoints || trace . points ;
166
165
167
166
// repeatable pseudorandom number generator
@@ -258,7 +257,60 @@ function plotPoints(sel, plotinfo, trace, t) {
258
257
. call ( Drawing . translatePoints , xa , ya ) ;
259
258
}
260
259
260
+ function plotBoxMean ( sel , axes , trace , t ) {
261
+ var posAxis = axes . pos ;
262
+ var valAxis = axes . val ;
263
+ var bPos = t . bPos ;
264
+ var bPosPxOffset = t . bPosPxOffset || 0 ;
265
+
266
+ // to support for one-sided box
267
+ var bdPos0 ;
268
+ var bdPos1 ;
269
+ if ( Array . isArray ( t . bdPos ) ) {
270
+ bdPos0 = t . bdPos [ 0 ] ;
271
+ bdPos1 = t . bdPos [ 1 ] ;
272
+ } else {
273
+ bdPos0 = t . bdPos ;
274
+ bdPos1 = t . bdPos ;
275
+ }
276
+
277
+ sel . selectAll ( 'path.mean' )
278
+ . data ( Lib . identity )
279
+ . enter ( ) . append ( 'path' )
280
+ . attr ( 'class' , 'mean' )
281
+ . style ( {
282
+ fill : 'none' ,
283
+ 'vector-effect' : 'non-scaling-stroke'
284
+ } )
285
+ . each ( function ( d ) {
286
+ var posc = posAxis . c2p ( d . pos + bPos , true ) + bPosPxOffset ;
287
+ var pos0 = posAxis . c2p ( d . pos + bPos - bdPos0 , true ) + bPosPxOffset ;
288
+ var pos1 = posAxis . c2p ( d . pos + bPos + bdPos1 , true ) + bPosPxOffset ;
289
+ var m = valAxis . c2p ( d . mean , true ) ;
290
+ var sl = valAxis . c2p ( d . mean - d . sd , true ) ;
291
+ var sh = valAxis . c2p ( d . mean + d . sd , true ) ;
292
+
293
+ if ( trace . orientation === 'h' ) {
294
+ d3 . select ( this ) . attr ( 'd' ,
295
+ 'M' + m + ',' + pos0 + 'V' + pos1 +
296
+ ( trace . boxmean === 'sd' ?
297
+ 'm0,0L' + sl + ',' + posc + 'L' + m + ',' + pos0 + 'L' + sh + ',' + posc + 'Z' :
298
+ '' )
299
+ ) ;
300
+ } else {
301
+ d3 . select ( this ) . attr ( 'd' ,
302
+ 'M' + pos0 + ',' + m + 'H' + pos1 +
303
+ ( trace . boxmean === 'sd' ?
304
+ 'm0,0L' + posc + ',' + sl + 'L' + pos0 + ',' + m + 'L' + posc + ',' + sh + 'Z' :
305
+ '' )
306
+ ) ;
307
+ }
308
+ } ) ;
309
+ }
310
+
261
311
module . exports = {
262
312
plot : plot ,
263
- plotPoints : plotPoints
313
+ plotBoxAndWhiskers : plotBoxAndWhiskers ,
314
+ plotPoints : plotPoints ,
315
+ plotBoxMean : plotBoxMean
264
316
} ;
0 commit comments