@@ -12,7 +12,6 @@ var createScatter = require('regl-scatter2d');
1212var createLine = require ( 'regl-line2d' ) ;
1313var createError = require ( 'regl-error2d' ) ;
1414var cluster = require ( 'point-cluster' ) ;
15- var arrayRange = require ( 'array-range' ) ;
1615var Text = require ( 'gl-text' ) ;
1716
1817var Registry = require ( '../../registry' ) ;
@@ -116,7 +115,6 @@ function calc(gd, trace) {
116115 opts . marker . snap = stash . tree || TOO_MANY_POINTS ;
117116 }
118117
119- // save scene opts batch
120118 scene . lineOptions . push ( opts . line ) ;
121119 scene . errorXOptions . push ( opts . errorX ) ;
122120 scene . errorYOptions . push ( opts . errorY ) ;
@@ -127,8 +125,9 @@ function calc(gd, trace) {
127125 scene . textOptions . push ( opts . text ) ;
128126 scene . textSelectedOptions . push ( opts . textSel ) ;
129127 scene . textUnselectedOptions . push ( opts . textUnsel ) ;
128+ scene . selectBatch . push ( [ ] ) ;
129+ scene . unselectBatch . push ( [ ] ) ;
130130
131- // stash scene ref
132131 stash . _scene = scene ;
133132 stash . index = scene . count ;
134133 stash . x = x ;
@@ -146,7 +145,6 @@ function expandForErrorBars(trace, ax, opts) {
146145 extremes . max = extremes . max . concat ( errExt . max ) ;
147146}
148147
149- // create scene options
150148function sceneOptions ( gd , subplot , trace , positions , x , y ) {
151149 var opts = convert . style ( gd , trace ) ;
152150
@@ -193,13 +191,12 @@ function sceneOptions(gd, subplot, trace, positions, x, y) {
193191 return opts ;
194192}
195193
196-
197194// make sure scene exists on subplot, return it
198195function sceneUpdate ( gd , subplot ) {
199196 var scene = subplot . _scene ;
200197
201198 var resetOpts = {
202- // number of traces in subplot, since scene:subplot → 1:1
199+ // number of traces in subplot, since scene:subplot -> 1:1
203200 count : 0 ,
204201 // whether scene requires init hook in plot call (dirty plot call)
205202 dirty : true ,
@@ -213,19 +210,20 @@ function sceneUpdate(gd, subplot) {
213210 errorYOptions : [ ] ,
214211 textOptions : [ ] ,
215212 textSelectedOptions : [ ] ,
216- textUnselectedOptions : [ ]
213+ textUnselectedOptions : [ ] ,
214+ // selection batches
215+ selectBatch : [ ] ,
216+ unselectBatch : [ ]
217217 } ;
218218
219+ // regl- component stubs, initialized in dirty plot call
219220 var initOpts = {
220- selectBatch : null ,
221- unselectBatch : null ,
222- // regl- component stubs, initialized in dirty plot call
223221 fill2d : false ,
224222 scatter2d : false ,
225223 error2d : false ,
226224 line2d : false ,
227225 glText : false ,
228- select2d : null
226+ select2d : false
229227 } ;
230228
231229 if ( ! subplot . _scene ) {
@@ -276,17 +274,22 @@ function sceneUpdate(gd, subplot) {
276274 if ( scene . errorXOptions [ i ] ) error2d . draw ( i ) ;
277275 if ( scene . errorYOptions [ i ] ) error2d . draw ( i + count ) ;
278276 }
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+ }
281285 }
282286 if ( glText [ i ] && scene . textOptions [ i ] ) {
283287 glText [ i ] . render ( ) ;
284288 }
285289 }
286290
287- if ( scatter2d && select2d && selectBatch ) {
291+ if ( select2d ) {
288292 select2d . draw ( selectBatch ) ;
289- scatter2d . draw ( unselectBatch ) ;
290293 }
291294
292295 scene . dirty = false ;
@@ -325,7 +328,7 @@ function sceneUpdate(gd, subplot) {
325328 } ;
326329 }
327330
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
329332 if ( ! scene . dirty ) {
330333 Lib . extendFlat ( scene , resetOpts ) ;
331334 }
@@ -363,6 +366,7 @@ function plot(gd, subplot, cdata) {
363366 return ;
364367 }
365368
369+ var count = scene . count ;
366370 var regl = fullLayout . _glcanvas . data ( ) [ 0 ] . regl ;
367371
368372 // that is needed for fills
@@ -383,28 +387,28 @@ function plot(gd, subplot, cdata) {
383387 scene . fill2d = createLine ( regl ) ;
384388 }
385389 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 ++ ) {
388392 scene . glText [ i ] = new Text ( regl ) ;
389393 }
390394 }
391395
392396 // update main marker options
393397 if ( scene . glText ) {
394- if ( scene . count > scene . glText . length ) {
398+ if ( count > scene . glText . length ) {
395399 // add gl text marker
396- var textsToAdd = scene . count - scene . glText . length ;
400+ var textsToAdd = count - scene . glText . length ;
397401 for ( i = 0 ; i < textsToAdd ; i ++ ) {
398402 scene . glText . push ( new Text ( regl ) ) ;
399403 }
400- } else if ( scene . count < scene . glText . length ) {
404+ } else if ( count < scene . glText . length ) {
401405 // 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 ) ;
404408 removedTexts . forEach ( function ( text ) { text . destroy ( ) ; } ) ;
405409 }
406410
407- for ( i = 0 ; i < scene . count ; i ++ ) {
411+ for ( i = 0 ; i < count ; i ++ ) {
408412 scene . glText [ i ] . update ( scene . textOptions [ i ] ) ;
409413 }
410414 }
@@ -437,7 +441,7 @@ function plot(gd, subplot, cdata) {
437441 }
438442
439443 // 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 ) ;
441445 if ( scene . fill2d ) {
442446 scene . fillOptions = scene . fillOptions . map ( function ( fillOptions , i ) {
443447 var cdscatter = cdata [ i ] ;
@@ -556,13 +560,11 @@ function plot(gd, subplot, cdata) {
556560 }
557561
558562 // form batch arrays, and check for selected points
559- scene . selectBatch = null ;
560- scene . unselectBatch = null ;
561563 var dragmode = fullLayout . dragmode ;
562564 var selectMode = dragmode === 'lasso' || dragmode === 'select' ;
563565 var clickSelectEnabled = fullLayout . clickmode . indexOf ( 'select' ) > - 1 ;
564566
565- for ( i = 0 ; i < cdata . length ; i ++ ) {
567+ for ( i = 0 ; i < count ; i ++ ) {
566568 var cd0 = cdata [ i ] [ 0 ] ;
567569 var trace = cd0 . trace ;
568570 var stash = cd0 . t ;
@@ -574,11 +576,6 @@ function plot(gd, subplot, cdata) {
574576 if ( trace . selectedpoints || selectMode || clickSelectEnabled ) {
575577 if ( ! selectMode ) selectMode = true ;
576578
577- if ( ! scene . selectBatch ) {
578- scene . selectBatch = [ ] ;
579- scene . unselectBatch = [ ] ;
580- }
581-
582579 // regenerate scene batch, if traces number changed during selection
583580 if ( trace . selectedpoints ) {
584581 var selPts = scene . selectBatch [ index ] = Lib . selIndices2selPoints ( trace ) ;
@@ -610,21 +607,24 @@ function plot(gd, subplot, cdata) {
610607 }
611608 }
612609
613-
614610 if ( selectMode ) {
615- // create select2d
611+ // create scatter instance by cloning scatter2d
616612 if ( ! scene . select2d ) {
617- // create scatter instance by cloning scatter2d
618613 scene . select2d = createScatter ( fullLayout . _glcanvas . data ( ) [ 1 ] . regl ) ;
619614 }
620615
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 ) ;
626625 }
627626
627+ // use selected style on 'focus' canvas
628628 if ( scene . select2d ) {
629629 scene . select2d . update ( scene . markerOptions ) ;
630630 scene . select2d . update ( scene . markerSelectedOptions ) ;
@@ -639,9 +639,9 @@ function plot(gd, subplot, cdata) {
639639 } ) ;
640640 }
641641 } else {
642+ // reset 'context' scatter2d opts to base opts,
643+ // thus unsetting markerUnselectedOptions from selection
642644 if ( scene . scatter2d ) {
643- // reset scatter2d opts to base opts,
644- // thus unsetting markerUnselectedOptions from selection
645645 scene . scatter2d . update ( scene . markerOptions ) ;
646646 }
647647 }
@@ -680,7 +680,6 @@ function plot(gd, subplot, cdata) {
680680 }
681681}
682682
683-
684683function hoverPoints ( pointData , xval , yval , hovermode ) {
685684 var cd = pointData . cd ;
686685 var stash = cd [ 0 ] . t ;
@@ -758,7 +757,6 @@ function hoverPoints(pointData, xval, yval, hovermode) {
758757 return [ pointData ] ;
759758}
760759
761-
762760function calcHover ( pointData , x , y , trace ) {
763761 var xa = pointData . xa ;
764762 var ya = pointData . ya ;
@@ -861,7 +859,6 @@ function calcHover(pointData, x, y, trace) {
861859 return pointData ;
862860}
863861
864-
865862function selectPoints ( searchInfo , selectionTester ) {
866863 var cd = searchInfo . cd ;
867864 var selection = [ ] ;
@@ -871,23 +868,23 @@ function selectPoints(searchInfo, selectionTester) {
871868 var x = stash . x ;
872869 var y = stash . y ;
873870 var scene = stash . _scene ;
871+ var index = stash . index ;
874872
875873 if ( ! scene ) return selection ;
876874
877875 var hasText = subTypes . hasText ( trace ) ;
878876 var hasMarkers = subTypes . hasMarkers ( trace ) ;
879877 var hasOnlyLines = ! hasMarkers && ! hasText ;
878+
880879 if ( trace . visible !== true || hasOnlyLines ) return selection ;
881880
881+ var els = [ ] ;
882+ var unels = [ ] ;
883+
882884 // degenerate polygon does not enable selection
883885 // 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 ;
888886 if ( selectionTester !== false && ! selectionTester . degenerate ) {
889- els = [ ] , unels = [ ] ;
890- for ( i = 0 ; i < len ; i ++ ) {
887+ for ( var i = 0 ; i < len ; i ++ ) {
891888 if ( selectionTester . contains ( [ stash . xpx [ i ] , stash . ypx [ i ] ] , false , i , searchInfo ) ) {
892889 els . push ( i ) ;
893890 selection . push ( {
@@ -899,32 +896,27 @@ function selectPoints(searchInfo, selectionTester) {
899896 unels . push ( i ) ;
900897 }
901898 }
902- } else {
903- unels = arrayRange ( len ) ;
904899 }
905900
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 ;
911903
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 ) ;
921914 }
922915 }
923916
924- scene . selectBatch [ stash . index ] = els ;
925- scene . unselectBatch [ stash . index ] = unels ;
917+ scene . selectBatch [ index ] = els ;
918+ scene . unselectBatch [ index ] = unels ;
926919
927- // update text options
928920 if ( hasText ) {
929921 styleTextSelection ( cd ) ;
930922 }
@@ -946,7 +938,7 @@ function styleTextSelection(cd) {
946938 var opts = Lib . extendFlat ( { } , baseOpts ) ;
947939 var i , j ;
948940
949- if ( els && unels ) {
941+ if ( els . length || unels . length ) {
950942 var stc = selOpts . color ;
951943 var utc = unselOpts . color ;
952944 var base = baseOpts . color ;
0 commit comments