@@ -28,6 +28,7 @@ var createError = require('regl-error2d');
2828var rgba = require ( 'color-normalize' ) ;
2929var svgSdf = require ( 'svg-path-sdf' ) ;
3030var createRegl = require ( 'regl' ) ;
31+ var arrayRange = require ( 'array-range' ) ;
3132var fillHoverText = require ( '../scatter/fill_hover_text' ) ;
3233var isNumeric = require ( 'fast-isnumeric' ) ;
3334
@@ -122,7 +123,6 @@ function calc(container, trace) {
122123 }
123124 }
124125
125-
126126 calcColorscales ( trace ) ;
127127
128128 var options = sceneOptions ( container , subplot , trace , positions ) ;
@@ -396,7 +396,9 @@ function sceneOptions(container, subplot, trace, positions) {
396396 function makeSelectedOptions ( selected , markerOpts ) {
397397 var options = { } ;
398398
399- if ( selected . marker . symbol ) {
399+ if ( ! selected ) return options ;
400+
401+ if ( selected . marker && selected . marker . symbol ) {
400402 options = makeMarkerOptions ( extend ( { } , markerOpts , selected . marker ) ) ;
401403 }
402404
@@ -599,12 +601,15 @@ function sceneUpdate(container, subplot) {
599601 scene . error2d . draw ( i ) ;
600602 scene . error2d . draw ( i + scene . count ) ;
601603 }
602- if ( scene . scatter2d && ! scene . selectBatch ) {
603- scene . scatter2d . draw ( i ) ;
604+ if ( scene . scatter2d ) {
605+ // traces in no-selection mode
606+ if ( ! scene . selectBatch || ! scene . selectBatch [ i ] ) {
607+ scene . scatter2d . draw ( i ) ;
608+ }
604609 }
605610 }
606611
607- // persistent selection draw
612+ // draw traces in selection mode
608613 if ( scene . select2d && scene . selectBatch ) {
609614 scene . select2d . draw ( scene . selectBatch ) ;
610615 scene . scatter2d . draw ( scene . unselectBatch ) ;
@@ -740,8 +745,8 @@ function plot(container, subplot, cdata) {
740745 if ( ! cdata . length ) return ;
741746
742747 var layout = container . _fullLayout ;
743- var stash = cdata [ 0 ] [ 0 ] . t ;
744- var scene = stash . scene ;
748+ var scene = cdata [ 0 ] [ 0 ] . t . scene ;
749+ var dragmode = layout . dragmode ;
745750
746751 // we may have more subplots than initialized data due to Axes.getSubplots method
747752 if ( ! scene ) return ;
@@ -782,6 +787,7 @@ function plot(container, subplot, cdata) {
782787 scene . fill2d = createLine ( regl ) ;
783788 }
784789
790+ // update main marker options
785791 if ( scene . line2d ) {
786792 scene . line2d . update ( scene . lineOptions ) ;
787793 }
@@ -790,13 +796,7 @@ function plot(container, subplot, cdata) {
790796 scene . error2d . update ( errorBatch ) ;
791797 }
792798 if ( scene . scatter2d ) {
793- if ( ! scene . selectBatch ) {
794- scene . scatter2d . update ( scene . markerOptions ) ;
795- }
796- else {
797- scene . scatter2d . update ( scene . unselectedOptions ) ;
798- scene . select2d . update ( scene . selectedOptions ) ;
799- }
799+ scene . scatter2d . update ( scene . markerOptions ) ;
800800 }
801801 // fill requires linked traces, so we generate it's positions here
802802 if ( scene . fill2d ) {
@@ -888,21 +888,15 @@ function plot(container, subplot, cdata) {
888888 }
889889 }
890890
891- // make sure selection layer is initialized if we require selection
892- var dragmode = layout . dragmode ;
893-
894- if ( dragmode === 'lasso' || dragmode === 'select' ) {
895- if ( scene . select2d && scene . selectBatch ) {
896- scene . scatter2d . update ( scene . unselectedOptions ) ;
897- }
898- }
891+ var selectMode = dragmode === 'lasso' || dragmode === 'select' ;
899892
900893 // provide viewport and range
901894 var vpRange = cdata . map ( function ( cdscatter ) {
902895 if ( ! cdscatter || ! cdscatter [ 0 ] || ! cdscatter [ 0 ] . trace ) return ;
903896 var cd = cdscatter [ 0 ] ;
904897 var trace = cd . trace ;
905898 var stash = cd . t ;
899+ var id = stash . index ;
906900 var x = stash . rawx ,
907901 y = stash . rawy ;
908902
@@ -924,30 +918,16 @@ function plot(container, subplot, cdata) {
924918 ( height - vpSize . t ) - ( 1 - yaxis . domain [ 1 ] ) * vpSize . h
925919 ] ;
926920
927- if ( trace . selectedpoints || dragmode === 'lasso' || dragmode === 'select' ) {
928- // create select2d
929- if ( ! scene . select2d && scene . scatter2d ) {
930- var selectRegl = layout . _glcanvas . data ( ) [ 1 ] . regl ;
921+ if ( trace . selectedpoints || selectMode ) {
922+ if ( ! selectMode ) selectMode = true ;
931923
932- // create scatter instance by cloning scatter2d
933- scene . select2d = createScatter ( selectRegl , { clone : scene . scatter2d } ) ;
934- scene . select2d . update ( scene . selectedOptions ) ;
924+ if ( ! scene . selectBatch ) scene . selectBatch = [ ] ;
925+ if ( ! scene . unselectBatch ) scene . unselectBatch = [ ] ;
935926
936- // create selection style once we have something selected
937- if ( trace . selectedpoints && ! scene . selectBatch ) {
938- scene . selectBatch = Array ( scene . count ) ;
939- scene . unselectBatch = Array ( scene . count ) ;
940- scene . scatter2d . update ( scene . unselectedOptions ) ;
941- }
942- }
943- else {
944- // update selection positions, since they may have changed by panning or alike
945- scene . select2d . update ( scene . selectedOptions ) ;
946- }
927+ // regenerate scene batch, if traces number changed during selection
928+ if ( trace . selectedpoints ) {
929+ scene . selectBatch [ id ] = trace . selectedpoints ;
947930
948- // form unselected batch
949- if ( trace . selectedpoints && ! scene . unselectBatch [ stash . index ] ) {
950- scene . selectBatch [ stash . index ] = trace . selectedpoints ;
951931 var selPts = trace . selectedpoints ;
952932 var selDict = { } ;
953933 for ( i = 0 ; i < selPts . length ; i ++ ) {
@@ -957,7 +937,7 @@ function plot(container, subplot, cdata) {
957937 for ( i = 0 ; i < stash . count ; i ++ ) {
958938 if ( ! selDict [ i ] ) unselPts . push ( i ) ;
959939 }
960- scene . unselectBatch [ stash . index ] = unselPts ;
940+ scene . unselectBatch [ id ] = unselPts ;
961941 }
962942
963943 // precalculate px coords since we are not going to pan during select
@@ -979,6 +959,21 @@ function plot(container, subplot, cdata) {
979959 } : null ;
980960 } ) ;
981961
962+ if ( selectMode ) {
963+ // create select2d
964+ if ( ! scene . select2d ) {
965+ // create scatter instance by cloning scatter2d
966+ scene . select2d = createScatter ( layout . _glcanvas . data ( ) [ 1 ] . regl , { clone : scene . scatter2d } ) ;
967+ }
968+
969+ // update only traces with selection
970+ scene . scatter2d . update ( scene . unselectedOptions . map ( function ( opts , i ) {
971+ return scene . selectBatch [ i ] ? opts : null ;
972+ } ) ) ;
973+ scene . select2d . update ( scene . markerOptions ) ;
974+ scene . select2d . update ( scene . selectedOptions ) ;
975+ }
976+
982977 // uploat viewport/range data to GPU
983978 if ( scene . fill2d ) {
984979 scene . fill2d . update ( vpRange ) ;
@@ -1193,18 +1188,25 @@ function selectPoints(searchInfo, polygon) {
11931188 }
11941189 }
11951190 else {
1196- unels = Array ( stash . count ) ;
1197- for ( i = 0 ; i < stash . count ; i ++ ) {
1198- unels [ i ] = i ;
1199- }
1191+ unels = arrayRange ( stash . count ) ;
12001192 }
12011193
1202- // create selection style once we have something selected
1194+ // make sure selectBatch is created
12031195 if ( ! scene . selectBatch ) {
1204- scene . selectBatch = Array ( scene . count ) ;
1205- scene . unselectBatch = Array ( scene . count ) ;
1196+ scene . selectBatch = [ ] ;
1197+ scene . unselectBatch = [ ] ;
1198+ }
1199+
1200+ if ( ! scene . selectBatch [ stash . index ] ) {
1201+ // enter every trace select mode
1202+ for ( i = 0 ; i < scene . count ; i ++ ) {
1203+ scene . selectBatch [ i ] = [ ] ;
1204+ scene . unselectBatch [ i ] = [ ] ;
1205+ }
1206+ // we should turn scatter2d into unselected once we have any points selected
12061207 scene . scatter2d . update ( scene . unselectedOptions ) ;
12071208 }
1209+
12081210 scene . selectBatch [ stash . index ] = els ;
12091211 scene . unselectBatch [ stash . index ] = unels ;
12101212
0 commit comments