@@ -12,7 +12,6 @@ var createScatter = require('regl-scatter2d');
12
12
var createLine = require ( 'regl-line2d' ) ;
13
13
var createError = require ( 'regl-error2d' ) ;
14
14
var cluster = require ( 'point-cluster' ) ;
15
- var arrayRange = require ( 'array-range' ) ;
16
15
var Text = require ( 'gl-text' ) ;
17
16
18
17
var Registry = require ( '../../registry' ) ;
@@ -116,7 +115,6 @@ function calc(gd, trace) {
116
115
opts . marker . snap = stash . tree || TOO_MANY_POINTS ;
117
116
}
118
117
119
- // save scene opts batch
120
118
scene . lineOptions . push ( opts . line ) ;
121
119
scene . errorXOptions . push ( opts . errorX ) ;
122
120
scene . errorYOptions . push ( opts . errorY ) ;
@@ -127,8 +125,9 @@ function calc(gd, trace) {
127
125
scene . textOptions . push ( opts . text ) ;
128
126
scene . textSelectedOptions . push ( opts . textSel ) ;
129
127
scene . textUnselectedOptions . push ( opts . textUnsel ) ;
128
+ scene . selectBatch . push ( [ ] ) ;
129
+ scene . unselectBatch . push ( [ ] ) ;
130
130
131
- // stash scene ref
132
131
stash . _scene = scene ;
133
132
stash . index = scene . count ;
134
133
stash . x = x ;
@@ -146,7 +145,6 @@ function expandForErrorBars(trace, ax, opts) {
146
145
extremes . max = extremes . max . concat ( errExt . max ) ;
147
146
}
148
147
149
- // create scene options
150
148
function sceneOptions ( gd , subplot , trace , positions , x , y ) {
151
149
var opts = convert . style ( gd , trace ) ;
152
150
@@ -193,13 +191,12 @@ function sceneOptions(gd, subplot, trace, positions, x, y) {
193
191
return opts ;
194
192
}
195
193
196
-
197
194
// make sure scene exists on subplot, return it
198
195
function sceneUpdate ( gd , subplot ) {
199
196
var scene = subplot . _scene ;
200
197
201
198
var resetOpts = {
202
- // number of traces in subplot, since scene:subplot → 1:1
199
+ // number of traces in subplot, since scene:subplot -> 1:1
203
200
count : 0 ,
204
201
// whether scene requires init hook in plot call (dirty plot call)
205
202
dirty : true ,
@@ -213,19 +210,20 @@ function sceneUpdate(gd, subplot) {
213
210
errorYOptions : [ ] ,
214
211
textOptions : [ ] ,
215
212
textSelectedOptions : [ ] ,
216
- textUnselectedOptions : [ ]
213
+ textUnselectedOptions : [ ] ,
214
+ // selection batches
215
+ selectBatch : [ ] ,
216
+ unselectBatch : [ ]
217
217
} ;
218
218
219
+ // regl- component stubs, initialized in dirty plot call
219
220
var initOpts = {
220
- selectBatch : null ,
221
- unselectBatch : null ,
222
- // regl- component stubs, initialized in dirty plot call
223
221
fill2d : false ,
224
222
scatter2d : false ,
225
223
error2d : false ,
226
224
line2d : false ,
227
225
glText : false ,
228
- select2d : null
226
+ select2d : false
229
227
} ;
230
228
231
229
if ( ! subplot . _scene ) {
@@ -276,17 +274,22 @@ function sceneUpdate(gd, subplot) {
276
274
if ( scene . errorXOptions [ i ] ) error2d . draw ( i ) ;
277
275
if ( scene . errorYOptions [ i ] ) error2d . draw ( i + count ) ;
278
276
}
279
- if ( scatter2d && scene . markerOptions [ i ] && ( ! selectBatch || ! selectBatch [ i ] ) ) {
280
- scatter2d . draw ( i ) ;
277
+ if ( scatter2d && scene . markerOptions [ i ] ) {
278
+ if ( unselectBatch [ i ] . length ) {
279
+ var arg = Lib . repeat ( [ ] , scene . count ) ;
280
+ arg [ i ] = unselectBatch [ i ] ;
281
+ scatter2d . draw ( arg ) ;
282
+ } else if ( ! selectBatch [ i ] . length ) {
283
+ scatter2d . draw ( i ) ;
284
+ }
281
285
}
282
286
if ( glText [ i ] && scene . textOptions [ i ] ) {
283
287
glText [ i ] . render ( ) ;
284
288
}
285
289
}
286
290
287
- if ( scatter2d && select2d && selectBatch ) {
291
+ if ( select2d ) {
288
292
select2d . draw ( selectBatch ) ;
289
- scatter2d . draw ( unselectBatch ) ;
290
293
}
291
294
292
295
scene . dirty = false ;
@@ -325,7 +328,7 @@ function sceneUpdate(gd, subplot) {
325
328
} ;
326
329
}
327
330
328
- // In case if we have scene from the last calc - reset data
331
+ // in case if we have scene from the last calc - reset data
329
332
if ( ! scene . dirty ) {
330
333
Lib . extendFlat ( scene , resetOpts ) ;
331
334
}
@@ -363,6 +366,7 @@ function plot(gd, subplot, cdata) {
363
366
return ;
364
367
}
365
368
369
+ var count = scene . count ;
366
370
var regl = fullLayout . _glcanvas . data ( ) [ 0 ] . regl ;
367
371
368
372
// that is needed for fills
@@ -383,28 +387,28 @@ function plot(gd, subplot, cdata) {
383
387
scene . fill2d = createLine ( regl ) ;
384
388
}
385
389
if ( scene . glText === true ) {
386
- scene . glText = new Array ( scene . count ) ;
387
- for ( i = 0 ; i < scene . count ; i ++ ) {
390
+ scene . glText = new Array ( count ) ;
391
+ for ( i = 0 ; i < count ; i ++ ) {
388
392
scene . glText [ i ] = new Text ( regl ) ;
389
393
}
390
394
}
391
395
392
396
// update main marker options
393
397
if ( scene . glText ) {
394
- if ( scene . count > scene . glText . length ) {
398
+ if ( count > scene . glText . length ) {
395
399
// add gl text marker
396
- var textsToAdd = scene . count - scene . glText . length ;
400
+ var textsToAdd = count - scene . glText . length ;
397
401
for ( i = 0 ; i < textsToAdd ; i ++ ) {
398
402
scene . glText . push ( new Text ( regl ) ) ;
399
403
}
400
- } else if ( scene . count < scene . glText . length ) {
404
+ } else if ( count < scene . glText . length ) {
401
405
// remove gl text marker
402
- var textsToRemove = scene . glText . length - scene . count ;
403
- var removedTexts = scene . glText . splice ( scene . count , textsToRemove ) ;
406
+ var textsToRemove = scene . glText . length - count ;
407
+ var removedTexts = scene . glText . splice ( count , textsToRemove ) ;
404
408
removedTexts . forEach ( function ( text ) { text . destroy ( ) ; } ) ;
405
409
}
406
410
407
- for ( i = 0 ; i < scene . count ; i ++ ) {
411
+ for ( i = 0 ; i < count ; i ++ ) {
408
412
scene . glText [ i ] . update ( scene . textOptions [ i ] ) ;
409
413
}
410
414
}
@@ -437,7 +441,7 @@ function plot(gd, subplot, cdata) {
437
441
}
438
442
439
443
// fill requires linked traces, so we generate it's positions here
440
- scene . fillOrder = Lib . repeat ( null , scene . count ) ;
444
+ scene . fillOrder = Lib . repeat ( null , count ) ;
441
445
if ( scene . fill2d ) {
442
446
scene . fillOptions = scene . fillOptions . map ( function ( fillOptions , i ) {
443
447
var cdscatter = cdata [ i ] ;
@@ -556,13 +560,11 @@ function plot(gd, subplot, cdata) {
556
560
}
557
561
558
562
// form batch arrays, and check for selected points
559
- scene . selectBatch = null ;
560
- scene . unselectBatch = null ;
561
563
var dragmode = fullLayout . dragmode ;
562
564
var selectMode = dragmode === 'lasso' || dragmode === 'select' ;
563
565
var clickSelectEnabled = fullLayout . clickmode . indexOf ( 'select' ) > - 1 ;
564
566
565
- for ( i = 0 ; i < cdata . length ; i ++ ) {
567
+ for ( i = 0 ; i < count ; i ++ ) {
566
568
var cd0 = cdata [ i ] [ 0 ] ;
567
569
var trace = cd0 . trace ;
568
570
var stash = cd0 . t ;
@@ -574,11 +576,6 @@ function plot(gd, subplot, cdata) {
574
576
if ( trace . selectedpoints || selectMode || clickSelectEnabled ) {
575
577
if ( ! selectMode ) selectMode = true ;
576
578
577
- if ( ! scene . selectBatch ) {
578
- scene . selectBatch = [ ] ;
579
- scene . unselectBatch = [ ] ;
580
- }
581
-
582
579
// regenerate scene batch, if traces number changed during selection
583
580
if ( trace . selectedpoints ) {
584
581
var selPts = scene . selectBatch [ index ] = Lib . selIndices2selPoints ( trace ) ;
@@ -610,21 +607,24 @@ function plot(gd, subplot, cdata) {
610
607
}
611
608
}
612
609
613
-
614
610
if ( selectMode ) {
615
- // create select2d
611
+ // create scatter instance by cloning scatter2d
616
612
if ( ! scene . select2d ) {
617
- // create scatter instance by cloning scatter2d
618
613
scene . select2d = createScatter ( fullLayout . _glcanvas . data ( ) [ 1 ] . regl ) ;
619
614
}
620
615
621
- if ( scene . scatter2d && scene . selectBatch && scene . selectBatch . length ) {
622
- // update only traces with selection
623
- scene . scatter2d . update ( scene . markerUnselectedOptions . map ( function ( opts , i ) {
624
- return scene . selectBatch [ i ] ? opts : null ;
625
- } ) ) ;
616
+ // use unselected styles on 'context' canvas
617
+ if ( scene . scatter2d ) {
618
+ var unselOpts = new Array ( count ) ;
619
+ for ( i = 0 ; i < count ; i ++ ) {
620
+ unselOpts [ i ] = scene . selectBatch [ i ] . length || scene . unselectBatch [ i ] . length ?
621
+ scene . markerUnselectedOptions [ i ] :
622
+ { } ;
623
+ }
624
+ scene . scatter2d . update ( unselOpts ) ;
626
625
}
627
626
627
+ // use selected style on 'focus' canvas
628
628
if ( scene . select2d ) {
629
629
scene . select2d . update ( scene . markerOptions ) ;
630
630
scene . select2d . update ( scene . markerSelectedOptions ) ;
@@ -639,9 +639,9 @@ function plot(gd, subplot, cdata) {
639
639
} ) ;
640
640
}
641
641
} else {
642
+ // reset 'context' scatter2d opts to base opts,
643
+ // thus unsetting markerUnselectedOptions from selection
642
644
if ( scene . scatter2d ) {
643
- // reset scatter2d opts to base opts,
644
- // thus unsetting markerUnselectedOptions from selection
645
645
scene . scatter2d . update ( scene . markerOptions ) ;
646
646
}
647
647
}
@@ -680,7 +680,6 @@ function plot(gd, subplot, cdata) {
680
680
}
681
681
}
682
682
683
-
684
683
function hoverPoints ( pointData , xval , yval , hovermode ) {
685
684
var cd = pointData . cd ;
686
685
var stash = cd [ 0 ] . t ;
@@ -758,7 +757,6 @@ function hoverPoints(pointData, xval, yval, hovermode) {
758
757
return [ pointData ] ;
759
758
}
760
759
761
-
762
760
function calcHover ( pointData , x , y , trace ) {
763
761
var xa = pointData . xa ;
764
762
var ya = pointData . ya ;
@@ -861,7 +859,6 @@ function calcHover(pointData, x, y, trace) {
861
859
return pointData ;
862
860
}
863
861
864
-
865
862
function selectPoints ( searchInfo , selectionTester ) {
866
863
var cd = searchInfo . cd ;
867
864
var selection = [ ] ;
@@ -871,23 +868,23 @@ function selectPoints(searchInfo, selectionTester) {
871
868
var x = stash . x ;
872
869
var y = stash . y ;
873
870
var scene = stash . _scene ;
871
+ var index = stash . index ;
874
872
875
873
if ( ! scene ) return selection ;
876
874
877
875
var hasText = subTypes . hasText ( trace ) ;
878
876
var hasMarkers = subTypes . hasMarkers ( trace ) ;
879
877
var hasOnlyLines = ! hasMarkers && ! hasText ;
878
+
880
879
if ( trace . visible !== true || hasOnlyLines ) return selection ;
881
880
881
+ var els = [ ] ;
882
+ var unels = [ ] ;
883
+
882
884
// degenerate polygon does not enable selection
883
885
// filter out points by visible scatter ones
884
- var els = null ;
885
- var unels = null ;
886
- // FIXME: clearing selection does not work here
887
- var i ;
888
886
if ( selectionTester !== false && ! selectionTester . degenerate ) {
889
- els = [ ] , unels = [ ] ;
890
- for ( i = 0 ; i < len ; i ++ ) {
887
+ for ( var i = 0 ; i < len ; i ++ ) {
891
888
if ( selectionTester . contains ( [ stash . xpx [ i ] , stash . ypx [ i ] ] , false , i , searchInfo ) ) {
892
889
els . push ( i ) ;
893
890
selection . push ( {
@@ -899,32 +896,27 @@ function selectPoints(searchInfo, selectionTester) {
899
896
unels . push ( i ) ;
900
897
}
901
898
}
902
- } else {
903
- unels = arrayRange ( len ) ;
904
899
}
905
900
906
- // make sure selectBatch is created
907
- if ( ! scene . selectBatch ) {
908
- scene . selectBatch = [ ] ;
909
- scene . unselectBatch = [ ] ;
910
- }
901
+ if ( hasMarkers ) {
902
+ var scatter2d = scene . scatter2d ;
911
903
912
- if ( ! scene . selectBatch [ stash . index ] ) {
913
- // enter every trace select mode
914
- for ( i = 0 ; i < scene . count ; i ++ ) {
915
- scene . selectBatch [ i ] = [ ] ;
916
- scene . unselectBatch [ i ] = [ ] ;
917
- }
918
- // we should turn scatter2d into unselected once we have any points selected
919
- if ( hasMarkers ) {
920
- scene . scatter2d . update ( scene . markerUnselectedOptions ) ;
904
+ if ( ! els . length && ! unels . length ) {
905
+ // reset to base styles when clearing
906
+ var baseOpts = new Array ( scene . count ) ;
907
+ baseOpts [ index ] = scene . markerOptions [ index ] ;
908
+ scatter2d . update . apply ( scatter2d , baseOpts ) ;
909
+ } else if ( ! scene . selectBatch [ index ] . length && ! scene . unselectBatch [ index ] . length ) {
910
+ // set unselected styles on 'context' canvas (if not done already)
911
+ var unselOpts = new Array ( scene . count ) ;
912
+ unselOpts [ index ] = scene . markerUnselectedOptions [ index ] ;
913
+ scatter2d . update . apply ( scatter2d , unselOpts ) ;
921
914
}
922
915
}
923
916
924
- scene . selectBatch [ stash . index ] = els ;
925
- scene . unselectBatch [ stash . index ] = unels ;
917
+ scene . selectBatch [ index ] = els ;
918
+ scene . unselectBatch [ index ] = unels ;
926
919
927
- // update text options
928
920
if ( hasText ) {
929
921
styleTextSelection ( cd ) ;
930
922
}
@@ -946,7 +938,7 @@ function styleTextSelection(cd) {
946
938
var opts = Lib . extendFlat ( { } , baseOpts ) ;
947
939
var i , j ;
948
940
949
- if ( els && unels ) {
941
+ if ( els . length || unels . length ) {
950
942
var stc = selOpts . color ;
951
943
var utc = unselOpts . color ;
952
944
var base = baseOpts . color ;
0 commit comments