@@ -41,21 +41,25 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
4141
4242 // BUILD LINES AND FILLS
4343 var prevpath = '' ,
44- tozero , tonext , nexttonext ;
44+ ownFillEl3 , ownFillDir , tonext , nexttonext ;
4545
4646 scattertraces . each ( function ( d ) {
4747 var trace = d [ 0 ] . trace ,
4848 line = trace . line ,
4949 tr = d3 . select ( this ) ;
5050 if ( trace . visible !== true ) return ;
5151
52+ ownFillDir = trace . fill . charAt ( trace . fill . length - 1 ) ;
53+ if ( ownFillDir !== 'x' && ownFillDir !== 'y' ) ownFillDir = '' ;
54+
5255 d [ 0 ] . node3 = tr ; // store node for tweaking by selectPoints
5356
5457 arraysToCalcdata ( d ) ;
5558
5659 if ( ! subTypes . hasLines ( trace ) && trace . fill === 'none' ) return ;
5760
5861 var thispath ,
62+ thisrevpath ,
5963 // fullpath is all paths for this curve, joined together straight
6064 // across gaps, for filling
6165 fullpath = '' ,
@@ -67,12 +71,12 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
6771 // make the fill-to-zero path now, so it shows behind the line
6872 // fill to next puts the fill associated with one trace
6973 // grouped with the previous
70- if ( trace . fill . substr ( 0 , 6 ) === 'tozero' ||
74+ if ( trace . fill . substr ( 0 , 6 ) === 'tozero' || trace . fill === 'toself' ||
7175 ( trace . fill . substr ( 0 , 2 ) === 'to' && ! prevpath ) ) {
72- tozero = tr . append ( 'path' )
76+ ownFillEl3 = tr . append ( 'path' )
7377 . classed ( 'js-fill' , true ) ;
7478 }
75- else tozero = null ;
79+ else ownFillEl3 = null ;
7680
7781 // make the fill-to-next path now for the NEXT trace, so it shows
7882 // behind both lines.
@@ -102,7 +106,7 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
102106
103107 revpathfn = function ( pts ) {
104108 // note: this is destructive (reverses pts in place) so can't use pts after this
105- return 'L' + revpathbase ( pts . reverse ( ) ) . substr ( 1 ) ;
109+ return revpathbase ( pts . reverse ( ) ) ;
106110 } ;
107111
108112 var segments = linePoints ( d , {
@@ -121,27 +125,58 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
121125 for ( var i = 0 ; i < segments . length ; i ++ ) {
122126 var pts = segments [ i ] ;
123127 thispath = pathfn ( pts ) ;
124- fullpath += fullpath ? ( 'L' + thispath . substr ( 1 ) ) : thispath ;
125- revpath = revpathfn ( pts ) + revpath ;
128+ thisrevpath = revpathfn ( pts ) ;
129+ if ( ! fullpath ) {
130+ fullpath = thispath ;
131+ revpath = thisrevpath ;
132+ }
133+ else if ( ownFillDir ) {
134+ fullpath += 'L' + thispath . substr ( 1 ) ;
135+ revpath = thisrevpath + ( 'L' + revpath . substr ( 1 ) ) ;
136+ }
137+ else {
138+ fullpath += 'Z' + thispath ;
139+ revpath = thisrevpath + 'Z' + revpath ;
140+ }
126141 if ( subTypes . hasLines ( trace ) && pts . length > 1 ) {
127142 tr . append ( 'path' ) . classed ( 'js-line' , true ) . attr ( 'd' , thispath ) ;
128143 }
129144 }
130- if ( tozero ) {
145+ if ( ownFillEl3 ) {
131146 if ( pt0 && pt1 ) {
132- if ( trace . fill . charAt ( trace . fill . length - 1 ) === 'y' ) {
133- pt0 [ 1 ] = pt1 [ 1 ] = ya . c2p ( 0 , true ) ;
147+ if ( ownFillDir ) {
148+ if ( ownFillDir === 'y' ) {
149+ pt0 [ 1 ] = pt1 [ 1 ] = ya . c2p ( 0 , true ) ;
150+ }
151+ else if ( ownFillDir === 'x' ) {
152+ pt0 [ 0 ] = pt1 [ 0 ] = xa . c2p ( 0 , true ) ;
153+ }
154+
155+ // fill to zero: full trace path, plus extension of
156+ // the endpoints to the appropriate axis
157+ ownFillEl3 . attr ( 'd' , fullpath + 'L' + pt1 + 'L' + pt0 + 'Z' ) ;
134158 }
135- else pt0 [ 0 ] = pt1 [ 0 ] = xa . c2p ( 0 , true ) ;
136-
137- // fill to zero: full trace path, plus extension of
138- // the endpoints to the appropriate axis
139- tozero . attr ( 'd' , fullpath + 'L' + pt1 + 'L' + pt0 + 'Z' ) ;
159+ // fill to self: just join the path to itself
160+ else ownFillEl3 . attr ( 'd' , fullpath + 'Z' ) ;
140161 }
141162 }
142163 else if ( trace . fill . substr ( 0 , 6 ) === 'tonext' && fullpath && prevpath ) {
143164 // fill to next: full trace path, plus the previous path reversed
144- tonext . attr ( 'd' , fullpath + prevpath + 'Z' ) ;
165+ if ( trace . fill === 'tonext' ) {
166+ // tonext: for use by concentric shapes, like manually constructed
167+ // contours, we just add the two paths closed on themselves.
168+ // This makes strange results if one path is *not* entirely
169+ // inside the other, but then that is a strange usage.
170+ tonext . attr ( 'd' , fullpath + 'Z' + prevpath + 'Z' ) ;
171+ }
172+ else {
173+ // tonextx/y: for now just connect endpoints with lines. This is
174+ // the correct behavior if the endpoints are at the same value of
175+ // y/x, but if they *aren't*, we should ideally do more complicated
176+ // things depending on whether the new endpoint projects onto the
177+ // existing curve or off the end of it
178+ tonext . attr ( 'd' , fullpath + 'L' + prevpath . substr ( 1 ) + 'Z' ) ;
179+ }
145180 }
146181 prevpath = revpath ;
147182 }
0 commit comments