@@ -39,8 +39,8 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
3939 if ( yReduce === undefined )
4040 yReduce = xReduce == null && yValue == null && sizeValue == null && xValue != null ? "count" : null ;
4141
42- const { zero : xZero } = x ;
43- const { zero : yZero } = y ;
42+ let { zero : xZero } = x ;
43+ let { zero : yZero } = y ;
4444 const { value : colorValue , reduce : colorReduce , color : colorColor } = color ;
4545 const { value : fxValue } = fx ;
4646 const { value : fyValue } = fy ;
@@ -64,7 +64,7 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
6464 fx = valueof ( data , fxValue ) ; // TODO Should we still materialize if heuristic doesn't depend on it?
6565 fy = valueof ( data , fyValue ) ;
6666
67- let fill , stroke , z , fillReduce , strokeReduce , zReduce ;
67+ let z , zReduce ;
6868
6969 // Propagate the x and y labels (field names), if any.
7070 if ( x ) x . label = labelof ( xValue ) ;
@@ -92,18 +92,18 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
9292 : null ;
9393 }
9494
95+ let colorMode ; // "fill" or "stroke"
96+
9597 // Determine the mark implementation.
9698 if ( mark != null ) {
9799 switch ( `${ mark } ` . toLowerCase ( ) ) {
98100 case "dot" :
99101 mark = dot ;
100- stroke = color ?? colorColor ;
101- strokeReduce = colorReduce ;
102+ colorMode = "stroke" ;
102103 break ;
103104 case "line" :
104105 mark = x && y ? line : x ? lineX : lineY ; // 1d line by index
105- stroke = color ?? colorColor ;
106- strokeReduce = colorReduce ;
106+ colorMode = "stroke" ;
107107 if ( isHighCardinality ( color ) ) z = null ; // TODO only if z not set by user
108108 break ;
109109 case "area" :
@@ -117,14 +117,12 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
117117 : x
118118 ? areaX
119119 : areaY ; // 1d area by index
120- fill = color ?? colorColor ;
121- fillReduce = colorReduce ;
120+ colorMode = "fill" ;
122121 if ( isHighCardinality ( color ) ) z = null ; // TODO only if z not set by user
123122 break ;
124123 case "rule" :
125124 mark = x ? ruleX : ruleY ;
126- stroke = color ?? colorColor ;
127- strokeReduce = colorReduce ;
125+ colorMode = "stroke" ;
128126 break ;
129127 case "bar" :
130128 mark =
@@ -149,23 +147,17 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
149147 : isOrdinal ( y )
150148 ? barX
151149 : barY ;
152- fill = color ?? colorColor ;
153- fillReduce = colorReduce ;
150+ colorMode = "fill" ;
154151 break ;
155152 default :
156153 throw new Error ( `invalid mark: ${ mark } ` ) ;
157154 }
158155 }
159156
160157 // Determine the mark options.
161- let options = { x, y, fill , stroke , z, r : size , fx, fy} ;
158+ let options = { x, y, [ colorMode ] : color ?? colorColor , z, r : size , fx, fy} ;
162159 let transform ;
163- let transformOptions = {
164- fill : fillReduce ,
165- stroke : strokeReduce ,
166- z : zReduce ,
167- r : sizeReduce
168- } ;
160+ let transformOptions = { [ colorMode ] : colorReduce , z : zReduce , r : sizeReduce } ;
169161 if ( xReduce != null && yReduce != null ) {
170162 throw new Error ( `cannot reduce both x and y` ) ; // for now at least
171163 } else if ( yReduce != null ) {
@@ -182,12 +174,18 @@ export function auto(data, {x, y, fx, fy, color, size, mark} = {}) {
182174 }
183175 if ( transform ) options = transform ( transformOptions , options ) ;
184176
185- return marks (
186- fx || fy ? frame ( { strokeOpacity : 0.1 } ) : null ,
187- xZero ? ruleX ( [ 0 ] ) : null ,
188- yZero ? ruleY ( [ 0 ] ) : null ,
189- mark ( data , options )
190- ) ;
177+ // If zero-ness is not specified, default based on whether the resolved mark
178+ // type will include a zero baseline.
179+ if ( xZero === undefined ) xZero = transform !== binX && ( mark === barX || mark === areaX || mark === rectX ) ;
180+ if ( yZero === undefined ) yZero = transform !== binY && ( mark === barY || mark === areaY || mark === rectY ) ;
181+
182+ // In the case of filled marks (particularly bars and areas) the frame and
183+ // rules should come after the mark; in the case of stroked marks
184+ // (particularly dots and lines) they should come before the mark.
185+ const frames = fx || fy ? frame ( { strokeOpacity : 0.1 } ) : null ;
186+ const rules = [ xZero ? ruleX ( [ 0 ] ) : null , yZero ? ruleY ( [ 0 ] ) : null ] ;
187+ mark = mark ( data , options ) ;
188+ return colorMode === "stroke" ? marks ( frames , rules , mark ) : marks ( frames , mark , rules ) ;
191189}
192190
193191function isContinuous ( values ) {
0 commit comments