@@ -33,7 +33,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, transitionOpts, makeOnCo
3333
3434 selection = scatterlayer . selectAll ( 'g.trace' ) ;
3535
36- join = selection . data ( cdscatter , function ( d ) { return d [ 0 ] . trace . uid ; } ) ;
36+ join = selection . data ( cdscatter , function ( d ) { return d [ 0 ] . trace . uid ; } ) ;
3737
3838 // Append new traces:
3939 join . enter ( ) . append ( 'g' )
@@ -197,11 +197,19 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
197197 // revpath is fullpath reversed, for fill-to-next
198198 revpath = '' ,
199199 // functions for converting a point array to a path
200- pathfn , revpathbase , revpathfn ;
200+ pathfn , revpathbase , revpathfn ,
201+ // variables used before and after the data join
202+ pt0 , lastSegment , pt1 , thisPolygons ;
203+
204+ // initialize line join data / method
205+ var segments = [ ] ,
206+ lineSegments = [ ] ,
207+ makeUpdate = Lib . noop ;
201208
202209 ownFillEl3 = trace . _ownFill ;
203210
204211 if ( subTypes . hasLines ( trace ) || trace . fill !== 'none' ) {
212+
205213 if ( tonext ) {
206214 // This tells .style which trace to use for fill information:
207215 tonext . datum ( cdscatter ) ;
@@ -237,7 +245,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
237245 return revpathbase ( pts . reverse ( ) ) ;
238246 } ;
239247
240- var segments = linePoints ( cdscatter , {
248+ segments = linePoints ( cdscatter , {
241249 xaxis : xa ,
242250 yaxis : ya ,
243251 connectGaps : trace . connectgaps ,
@@ -250,24 +258,22 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
250258 // polygons for hover on fill
251259 // TODO: can we skip this if hoveron!=fills? That would mean we
252260 // need to redraw when you change hoveron...
253- var thisPolygons = trace . _polygons = new Array ( segments . length ) ;
261+ thisPolygons = trace . _polygons = new Array ( segments . length ) ;
254262 for ( i = 0 ; i < segments . length ; i ++ ) {
255263 trace . _polygons [ i ] = polygonTester ( segments [ i ] ) ;
256264 }
257265
258- var pt0 , lastSegment , pt1 ;
259-
260266 if ( segments . length ) {
261267 pt0 = segments [ 0 ] [ 0 ] ;
262268 lastSegment = segments [ segments . length - 1 ] ;
263269 pt1 = lastSegment [ lastSegment . length - 1 ] ;
264270 }
265271
266- var lineSegments = segments . filter ( function ( s ) {
272+ lineSegments = segments . filter ( function ( s ) {
267273 return s . length > 1 ;
268274 } ) ;
269275
270- var makeUpdate = function ( isEnter ) {
276+ makeUpdate = function ( isEnter ) {
271277 return function ( pts ) {
272278 thispath = pathfn ( pts ) ;
273279 thisrevpath = revpathfn ( pts ) ;
@@ -303,66 +309,66 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
303309 }
304310 } ;
305311 } ;
312+ }
306313
307- var lineJoin = tr . selectAll ( '.js-line' ) . data ( lineSegments ) ;
314+ var lineJoin = tr . selectAll ( '.js-line' ) . data ( lineSegments ) ;
308315
309- transition ( lineJoin . exit ( ) )
310- . style ( 'opacity' , 0 )
311- . remove ( ) ;
316+ transition ( lineJoin . exit ( ) )
317+ . style ( 'opacity' , 0 )
318+ . remove ( ) ;
312319
313- lineJoin . each ( makeUpdate ( false ) ) ;
320+ lineJoin . each ( makeUpdate ( false ) ) ;
314321
315- lineJoin . enter ( ) . append ( 'path' )
316- . classed ( 'js-line' , true )
317- . style ( 'vector-effect' , 'non-scaling-stroke' )
318- . call ( Drawing . lineGroupStyle )
319- . each ( makeUpdate ( true ) ) ;
322+ lineJoin . enter ( ) . append ( 'path' )
323+ . classed ( 'js-line' , true )
324+ . style ( 'vector-effect' , 'non-scaling-stroke' )
325+ . call ( Drawing . lineGroupStyle )
326+ . each ( makeUpdate ( true ) ) ;
320327
321- if ( segments . length ) {
322- if ( ownFillEl3 ) {
323- if ( pt0 && pt1 ) {
324- if ( ownFillDir ) {
325- if ( ownFillDir === 'y' ) {
326- pt0 [ 1 ] = pt1 [ 1 ] = ya . c2p ( 0 , true ) ;
327- }
328- else if ( ownFillDir === 'x' ) {
329- pt0 [ 0 ] = pt1 [ 0 ] = xa . c2p ( 0 , true ) ;
330- }
331-
332- // fill to zero: full trace path, plus extension of
333- // the endpoints to the appropriate axis
334- // For the sake of animations, wrap the points around so that
335- // the points on the axes are the first two points. Otherwise
336- // animations get a little crazy if the number of points changes.
337- transition ( ownFillEl3 ) . attr ( 'd' , 'M' + pt1 + 'L' + pt0 + 'L' + fullpath . substr ( 1 ) ) ;
338- } else {
339- // fill to self: just join the path to itself
340- transition ( ownFillEl3 ) . attr ( 'd' , fullpath + 'Z' ) ;
328+ if ( segments . length ) {
329+ if ( ownFillEl3 ) {
330+ if ( pt0 && pt1 ) {
331+ if ( ownFillDir ) {
332+ if ( ownFillDir === 'y' ) {
333+ pt0 [ 1 ] = pt1 [ 1 ] = ya . c2p ( 0 , true ) ;
334+ }
335+ else if ( ownFillDir === 'x' ) {
336+ pt0 [ 0 ] = pt1 [ 0 ] = xa . c2p ( 0 , true ) ;
341337 }
338+
339+ // fill to zero: full trace path, plus extension of
340+ // the endpoints to the appropriate axis
341+ // For the sake of animations, wrap the points around so that
342+ // the points on the axes are the first two points. Otherwise
343+ // animations get a little crazy if the number of points changes.
344+ transition ( ownFillEl3 ) . attr ( 'd' , 'M' + pt1 + 'L' + pt0 + 'L' + fullpath . substr ( 1 ) ) ;
345+ } else {
346+ // fill to self: just join the path to itself
347+ transition ( ownFillEl3 ) . attr ( 'd' , fullpath + 'Z' ) ;
342348 }
343349 }
344- else if ( trace . fill . substr ( 0 , 6 ) === 'tonext' && fullpath && prevRevpath ) {
345- // fill to next: full trace path, plus the previous path reversed
346- if ( trace . fill === 'tonext' ) {
347- // tonext: for use by concentric shapes, like manually constructed
348- // contours, we just add the two paths closed on themselves.
349- // This makes strange results if one path is *not* entirely
350- // inside the other, but then that is a strange usage.
351- transition ( tonext ) . attr ( 'd' , fullpath + 'Z' + prevRevpath + 'Z' ) ;
352- }
353- else {
354- // tonextx/y: for now just connect endpoints with lines. This is
355- // the correct behavior if the endpoints are at the same value of
356- // y/x, but if they *aren't*, we should ideally do more complicated
357- // things depending on whether the new endpoint projects onto the
358- // existing curve or off the end of it
359- transition ( tonext ) . attr ( 'd' , fullpath + 'L' + prevRevpath . substr ( 1 ) + 'Z' ) ;
360- }
361- trace . _polygons = trace . _polygons . concat ( prevPolygons ) ;
350+ }
351+ else if ( trace . fill . substr ( 0 , 6 ) === 'tonext' && fullpath && prevRevpath ) {
352+ // fill to next: full trace path, plus the previous path reversed
353+ if ( trace . fill === 'tonext' ) {
354+ // tonext: for use by concentric shapes, like manually constructed
355+ // contours, we just add the two paths closed on themselves.
356+ // This makes strange results if one path is *not* entirely
357+ // inside the other, but then that is a strange usage.
358+ transition ( tonext ) . attr ( 'd' , fullpath + 'Z' + prevRevpath + 'Z' ) ;
359+ }
360+ else {
361+ // tonextx/y: for now just connect endpoints with lines. This is
362+ // the correct behavior if the endpoints are at the same value of
363+ // y/x, but if they *aren't*, we should ideally do more complicated
364+ // things depending on whether the new endpoint projects onto the
365+ // existing curve or off the end of it
366+ transition ( tonext ) . attr ( 'd' , fullpath + 'L' + prevRevpath . substr ( 1 ) + 'Z' ) ;
362367 }
363- trace . _prevRevpath = revpath ;
364- trace . _prevPolygons = thisPolygons ;
368+ trace . _polygons = trace . _polygons . concat ( prevPolygons ) ;
365369 }
370+ trace . _prevRevpath = revpath ;
371+ trace . _prevPolygons = thisPolygons ;
366372 }
367373
368374
@@ -381,64 +387,78 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
381387 }
382388 }
383389
390+ function hideFilter ( ) {
391+ return false ;
392+ }
393+
384394 function makePoints ( d ) {
385395 var join , selection ;
396+
386397 var trace = d [ 0 ] . trace ,
387398 s = d3 . select ( this ) ,
388399 showMarkers = subTypes . hasMarkers ( trace ) ,
389400 showText = subTypes . hasText ( trace ) ;
390401
391- if ( ( ! showMarkers && ! showText ) || trace . visible !== true ) s . remove ( ) ;
392- else {
393- if ( showMarkers ) {
394- selection = s . selectAll ( 'path.point' ) ;
402+ var keyFunc = getKeyFunc ( trace ) ,
403+ markerFilter = hideFilter ,
404+ textFilter = hideFilter ;
395405
396- join = selection
397- . data ( trace . marker . maxdisplayed ? visFilter : Lib . identity , getKeyFunc ( trace ) ) ;
406+ if ( showMarkers ) {
407+ markerFilter = trace . marker . maxdisplayed ? visFilter : Lib . identity ;
408+ }
398409
399- var enter = join . enter ( ) . append ( 'path' )
400- . classed ( 'point' , true ) ;
410+ if ( showText ) {
411+ textFilter = trace . marker . maxdisplayed ? visFilter : Lib . identity ;
412+ }
401413
402- enter . call ( Drawing . pointStyle , trace )
403- . call ( Drawing . translatePoints , xa , ya , trace ) ;
414+ // marker points
404415
405- if ( hasTransition ) {
406- enter . style ( 'opacity' , 0 ) . transition ( )
407- . style ( 'opacity' , 1 ) ;
408- }
416+ selection = s . selectAll ( 'path.point' ) ;
409417
410- join . each ( function ( d ) {
411- var sel = transition ( d3 . select ( this ) ) ;
412- Drawing . translatePoint ( d , sel , xa , ya ) ;
413- Drawing . singlePointStyle ( d , sel , trace ) ;
414- } ) ;
418+ join = selection . data ( markerFilter , keyFunc ) ;
415419
416- if ( hasTransition ) {
417- join . exit ( ) . transition ( )
418- . style ( 'opacity' , 0 )
419- . remove ( ) ;
420- } else {
421- join . exit ( ) . remove ( ) ;
422- }
423- }
424- if ( showText ) {
425- selection = s . selectAll ( 'g' ) ;
420+ var enter = join . enter ( ) . append ( 'path' )
421+ . classed ( 'point' , true ) ;
426422
427- join = selection
428- . data ( trace . marker . maxdisplayed ? visFilter : Lib . identity ) ;
423+ enter . call ( Drawing . pointStyle , trace )
424+ . call ( Drawing . translatePoints , xa , ya , trace ) ;
429425
430- // each text needs to go in its own 'g' in case
431- // it gets converted to mathjax
432- join . enter ( ) . append ( 'g' )
433- . append ( 'text' )
434- . call ( Drawing . translatePoints , xa , ya ) ;
426+ if ( hasTransition ) {
427+ enter . style ( 'opacity' , 0 ) . transition ( )
428+ . style ( 'opacity' , 1 ) ;
429+ }
435430
436- selection
437- . call ( Drawing . translatePoints , xa , ya ) ;
431+ join . each ( function ( d ) {
432+ var sel = transition ( d3 . select ( this ) ) ;
433+ Drawing . translatePoint ( d , sel , xa , ya ) ;
434+ Drawing . singlePointStyle ( d , sel , trace ) ;
435+ } ) ;
438436
439- join . exit ( ) . remove ( ) ;
440- }
437+ if ( hasTransition ) {
438+ join . exit ( ) . transition ( )
439+ . style ( 'opacity' , 0 )
440+ . remove ( ) ;
441+ } else {
442+ join . exit ( ) . remove ( ) ;
441443 }
444+
445+ // text points
446+
447+ selection = s . selectAll ( 'g' ) ;
448+
449+ join = selection . data ( textFilter , keyFunc ) ;
450+
451+ // each text needs to go in its own 'g' in case
452+ // it gets converted to mathjax
453+ join . enter ( ) . append ( 'g' )
454+ . append ( 'text' ) ;
455+
456+ join . each ( function ( d ) {
457+ var sel = d3 . select ( this ) . select ( 'text' ) ;
458+ Drawing . translatePoint ( d , sel , xa , ya ) ;
459+ } ) ;
460+
461+ join . exit ( ) . remove ( ) ;
442462 }
443463
444464 // NB: selectAll is evaluated on instantiation:
0 commit comments