@@ -28,6 +28,7 @@ var createError = require('regl-error2d');
28
28
var rgba = require ( 'color-normalize' ) ;
29
29
var svgSdf = require ( 'svg-path-sdf' ) ;
30
30
var createRegl = require ( 'regl' ) ;
31
+ var arrayRange = require ( 'array-range' ) ;
31
32
var fillHoverText = require ( '../scatter/fill_hover_text' ) ;
32
33
var isNumeric = require ( 'fast-isnumeric' ) ;
33
34
@@ -122,7 +123,6 @@ function calc(container, trace) {
122
123
}
123
124
}
124
125
125
-
126
126
calcColorscales ( trace ) ;
127
127
128
128
var options = sceneOptions ( container , subplot , trace , positions ) ;
@@ -599,6 +599,7 @@ function sceneUpdate(container, subplot) {
599
599
scene . error2d . draw ( i ) ;
600
600
scene . error2d . draw ( i + scene . count ) ;
601
601
}
602
+
602
603
if ( scene . scatter2d && ! scene . selectBatch ) {
603
604
scene . scatter2d . draw ( i ) ;
604
605
}
@@ -740,8 +741,9 @@ function plot(container, subplot, cdata) {
740
741
if ( ! cdata . length ) return ;
741
742
742
743
var layout = container . _fullLayout ;
743
- var stash = cdata [ 0 ] [ 0 ] . t ;
744
- var scene = stash . scene ;
744
+ var scene = cdata [ 0 ] [ 0 ] . t . scene ;
745
+ var i ;
746
+ var dragmode = layout . dragmode ;
745
747
746
748
// we may have more subplots than initialized data due to Axes.getSubplots method
747
749
if ( ! scene ) return ;
@@ -782,6 +784,7 @@ function plot(container, subplot, cdata) {
782
784
scene . fill2d = createLine ( regl ) ;
783
785
}
784
786
787
+ // update main marker options
785
788
if ( scene . line2d ) {
786
789
scene . line2d . update ( scene . lineOptions ) ;
787
790
}
@@ -790,13 +793,7 @@ function plot(container, subplot, cdata) {
790
793
scene . error2d . update ( errorBatch ) ;
791
794
}
792
795
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
- }
796
+ scene . scatter2d . update ( scene . markerOptions ) ;
800
797
}
801
798
// fill requires linked traces, so we generate it's positions here
802
799
if ( scene . fill2d ) {
@@ -886,17 +883,77 @@ function plot(container, subplot, cdata) {
886
883
887
884
scene . fill2d . update ( scene . fillOptions ) ;
888
885
}
889
- }
890
886
891
- // make sure selection layer is initialized if we require selection
892
- var dragmode = layout . dragmode ;
893
887
894
- if ( dragmode === 'lasso' || dragmode === 'select' ) {
895
- if ( scene . select2d && scene . selectBatch ) {
896
- scene . scatter2d . update ( scene . unselectedOptions ) ;
888
+ // update selection
889
+ var hasSelectedPoints = false ;
890
+ for ( i = 0 ; i < cdata . length ; i ++ ) {
891
+ if ( cdata [ i ] [ 0 ] . trace . selectedpoints ) {
892
+ hasSelectedPoints = true ;
893
+ break ;
894
+ }
895
+ }
896
+
897
+ if ( scene . selectBatch || dragmode === 'lasso' || dragmode === 'select' || hasSelectedPoints ) {
898
+ var newSelectBatch , newUnselectBatch ;
899
+
900
+ // create select2d
901
+ if ( ! scene . select2d ) {
902
+ // create scatter instance by cloning scatter2d
903
+ scene . select2d = createScatter ( layout . _glcanvas . data ( ) [ 1 ] . regl , { clone : scene . scatter2d } ) ;
904
+ }
905
+
906
+ // regenerate scene batch, if traces number changed during selection
907
+ if ( scene . selectBatch || hasSelectedPoints ) {
908
+ if ( ! scene . selectBatch ) scene . selectBatch = [ ] ;
909
+ if ( ! scene . unselectBatch ) scene . unselectBatch = [ ] ;
910
+
911
+ newSelectBatch = Array ( scene . count ) ;
912
+ newUnselectBatch = Array ( scene . count ) ;
913
+
914
+ for ( var j = 0 ; j < newSelectBatch . length ; j ++ ) {
915
+ var trace = cdata [ j ] [ 0 ] . trace ;
916
+ var stash = cdata [ j ] [ 0 ] . t ;
917
+ var id = stash . index ;
918
+
919
+ // form unselected batch
920
+ if ( ! scene . unselectBatch [ id ] ) {
921
+ if ( trace . selectedpoints ) {
922
+ newSelectBatch [ id ] = trace . selectedpoints ;
923
+ var selPts = trace . selectedpoints ;
924
+ var selDict = { } ;
925
+ for ( i = 0 ; i < selPts . length ; i ++ ) {
926
+ selDict [ selPts [ i ] ] = true ;
927
+ }
928
+ var unselPts = [ ] ;
929
+ for ( i = 0 ; i < stash . count ; i ++ ) {
930
+ if ( ! selDict [ i ] ) unselPts . push ( i ) ;
931
+ }
932
+ newUnselectBatch [ id ] = unselPts ;
933
+ }
934
+ else {
935
+ newSelectBatch [ id ] = [ ] ;
936
+ newUnselectBatch [ id ] = arrayRange ( stash . count ) ;
937
+ }
938
+ }
939
+ else {
940
+ newSelectBatch [ id ] = scene . selectBatch [ id ] ;
941
+ newUnselectBatch [ id ] = scene . unselectBatch [ id ] ;
942
+ }
943
+ }
944
+
945
+ scene . selectBatch = newSelectBatch ;
946
+ scene . unselectBatch = newUnselectBatch ;
947
+
948
+ scene . scatter2d . update ( scene . unselectedOptions ) ;
949
+ }
950
+
951
+ scene . select2d . update ( scene . markerOptions ) ;
952
+ scene . select2d . update ( scene . selectedOptions ) ;
897
953
}
898
954
}
899
955
956
+
900
957
// provide viewport and range
901
958
var vpRange = cdata . map ( function ( cdscatter ) {
902
959
if ( ! cdscatter || ! cdscatter [ 0 ] || ! cdscatter [ 0 ] . trace ) return ;
@@ -925,41 +982,6 @@ function plot(container, subplot, cdata) {
925
982
] ;
926
983
927
984
if ( trace . selectedpoints || dragmode === 'lasso' || dragmode === 'select' ) {
928
- // create select2d
929
- if ( ! scene . select2d && scene . scatter2d ) {
930
- var selectRegl = layout . _glcanvas . data ( ) [ 1 ] . regl ;
931
-
932
- // create scatter instance by cloning scatter2d
933
- scene . select2d = createScatter ( selectRegl , { clone : scene . scatter2d } ) ;
934
- scene . select2d . update ( scene . selectedOptions ) ;
935
-
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
- }
947
-
948
- // form unselected batch
949
- if ( trace . selectedpoints && ! scene . unselectBatch [ stash . index ] ) {
950
- scene . selectBatch [ stash . index ] = trace . selectedpoints ;
951
- var selPts = trace . selectedpoints ;
952
- var selDict = { } ;
953
- for ( i = 0 ; i < selPts . length ; i ++ ) {
954
- selDict [ selPts [ i ] ] = true ;
955
- }
956
- var unselPts = [ ] ;
957
- for ( i = 0 ; i < stash . count ; i ++ ) {
958
- if ( ! selDict [ i ] ) unselPts . push ( i ) ;
959
- }
960
- scene . unselectBatch [ stash . index ] = unselPts ;
961
- }
962
-
963
985
// precalculate px coords since we are not going to pan during select
964
986
var xpx = Array ( stash . count ) , ypx = Array ( stash . count ) ;
965
987
for ( i = 0 ; i < stash . count ; i ++ ) {
@@ -1193,18 +1215,18 @@ function selectPoints(searchInfo, polygon) {
1193
1215
}
1194
1216
}
1195
1217
else {
1196
- unels = Array ( stash . count ) ;
1197
- for ( i = 0 ; i < stash . count ; i ++ ) {
1198
- unels [ i ] = i ;
1199
- }
1218
+ unels = arrayRange ( stash . count ) ;
1200
1219
}
1201
1220
1202
- // create selection style once we have something selected
1221
+ // make sure selectBatch is created
1203
1222
if ( ! scene . selectBatch ) {
1204
- scene . selectBatch = Array ( scene . count ) ;
1205
- scene . unselectBatch = Array ( scene . count ) ;
1223
+ scene . selectBatch = [ ] ;
1224
+ scene . unselectBatch = [ ] ;
1225
+
1226
+ // we should turn scatter2d into unselected once we have any points selected
1206
1227
scene . scatter2d . update ( scene . unselectedOptions ) ;
1207
1228
}
1229
+
1208
1230
scene . selectBatch [ stash . index ] = els ;
1209
1231
scene . unselectBatch [ stash . index ] = unels ;
1210
1232
0 commit comments