@@ -33,7 +33,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, transitionOpts, makeOnCo
33
33
34
34
selection = scatterlayer . selectAll ( 'g.trace' ) ;
35
35
36
- join = selection . data ( cdscatter , function ( d ) { return d [ 0 ] . trace . uid ; } ) ;
36
+ join = selection . data ( cdscatter , function ( d ) { return d [ 0 ] . trace . uid ; } ) ;
37
37
38
38
// Append new traces:
39
39
join . enter ( ) . append ( 'g' )
@@ -197,11 +197,19 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
197
197
// revpath is fullpath reversed, for fill-to-next
198
198
revpath = '' ,
199
199
// 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 ;
201
208
202
209
ownFillEl3 = trace . _ownFill ;
203
210
204
211
if ( subTypes . hasLines ( trace ) || trace . fill !== 'none' ) {
212
+
205
213
if ( tonext ) {
206
214
// This tells .style which trace to use for fill information:
207
215
tonext . datum ( cdscatter ) ;
@@ -237,7 +245,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
237
245
return revpathbase ( pts . reverse ( ) ) ;
238
246
} ;
239
247
240
- var segments = linePoints ( cdscatter , {
248
+ segments = linePoints ( cdscatter , {
241
249
xaxis : xa ,
242
250
yaxis : ya ,
243
251
connectGaps : trace . connectgaps ,
@@ -250,24 +258,22 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
250
258
// polygons for hover on fill
251
259
// TODO: can we skip this if hoveron!=fills? That would mean we
252
260
// need to redraw when you change hoveron...
253
- var thisPolygons = trace . _polygons = new Array ( segments . length ) ;
261
+ thisPolygons = trace . _polygons = new Array ( segments . length ) ;
254
262
for ( i = 0 ; i < segments . length ; i ++ ) {
255
263
trace . _polygons [ i ] = polygonTester ( segments [ i ] ) ;
256
264
}
257
265
258
- var pt0 , lastSegment , pt1 ;
259
-
260
266
if ( segments . length ) {
261
267
pt0 = segments [ 0 ] [ 0 ] ;
262
268
lastSegment = segments [ segments . length - 1 ] ;
263
269
pt1 = lastSegment [ lastSegment . length - 1 ] ;
264
270
}
265
271
266
- var lineSegments = segments . filter ( function ( s ) {
272
+ lineSegments = segments . filter ( function ( s ) {
267
273
return s . length > 1 ;
268
274
} ) ;
269
275
270
- var makeUpdate = function ( isEnter ) {
276
+ makeUpdate = function ( isEnter ) {
271
277
return function ( pts ) {
272
278
thispath = pathfn ( pts ) ;
273
279
thisrevpath = revpathfn ( pts ) ;
@@ -303,66 +309,66 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
303
309
}
304
310
} ;
305
311
} ;
312
+ }
306
313
307
- var lineJoin = tr . selectAll ( '.js-line' ) . data ( lineSegments ) ;
314
+ var lineJoin = tr . selectAll ( '.js-line' ) . data ( lineSegments ) ;
308
315
309
- transition ( lineJoin . exit ( ) )
310
- . style ( 'opacity' , 0 )
311
- . remove ( ) ;
316
+ transition ( lineJoin . exit ( ) )
317
+ . style ( 'opacity' , 0 )
318
+ . remove ( ) ;
312
319
313
- lineJoin . each ( makeUpdate ( false ) ) ;
320
+ lineJoin . each ( makeUpdate ( false ) ) ;
314
321
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 ) ) ;
320
327
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 ) ;
341
337
}
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' ) ;
342
348
}
343
349
}
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' ) ;
362
367
}
363
- trace . _prevRevpath = revpath ;
364
- trace . _prevPolygons = thisPolygons ;
368
+ trace . _polygons = trace . _polygons . concat ( prevPolygons ) ;
365
369
}
370
+ trace . _prevRevpath = revpath ;
371
+ trace . _prevPolygons = thisPolygons ;
366
372
}
367
373
368
374
@@ -381,64 +387,78 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
381
387
}
382
388
}
383
389
390
+ function hideFilter ( ) {
391
+ return false ;
392
+ }
393
+
384
394
function makePoints ( d ) {
385
395
var join , selection ;
396
+
386
397
var trace = d [ 0 ] . trace ,
387
398
s = d3 . select ( this ) ,
388
399
showMarkers = subTypes . hasMarkers ( trace ) ,
389
400
showText = subTypes . hasText ( trace ) ;
390
401
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 ;
395
405
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
+ }
398
409
399
- var enter = join . enter ( ) . append ( 'path' )
400
- . classed ( 'point' , true ) ;
410
+ if ( showText ) {
411
+ textFilter = trace . marker . maxdisplayed ? visFilter : Lib . identity ;
412
+ }
401
413
402
- enter . call ( Drawing . pointStyle , trace )
403
- . call ( Drawing . translatePoints , xa , ya , trace ) ;
414
+ // marker points
404
415
405
- if ( hasTransition ) {
406
- enter . style ( 'opacity' , 0 ) . transition ( )
407
- . style ( 'opacity' , 1 ) ;
408
- }
416
+ selection = s . selectAll ( 'path.point' ) ;
409
417
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 ) ;
415
419
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 ) ;
426
422
427
- join = selection
428
- . data ( trace . marker . maxdisplayed ? visFilter : Lib . identity ) ;
423
+ enter . call ( Drawing . pointStyle , trace )
424
+ . call ( Drawing . translatePoints , xa , ya , trace ) ;
429
425
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
+ }
435
430
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
+ } ) ;
438
436
439
- join . exit ( ) . remove ( ) ;
440
- }
437
+ if ( hasTransition ) {
438
+ join . exit ( ) . transition ( )
439
+ . style ( 'opacity' , 0 )
440
+ . remove ( ) ;
441
+ } else {
442
+ join . exit ( ) . remove ( ) ;
441
443
}
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 ( ) ;
442
462
}
443
463
444
464
// NB: selectAll is evaluated on instantiation:
0 commit comments