@@ -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 ) ;
@@ -599,6 +599,7 @@ function sceneUpdate(container, subplot) {
599599 scene . error2d . draw ( i ) ;
600600 scene . error2d . draw ( i + scene . count ) ;
601601 }
602+
602603 if ( scene . scatter2d && ! scene . selectBatch ) {
603604 scene . scatter2d . draw ( i ) ;
604605 }
@@ -740,8 +741,9 @@ function plot(container, subplot, cdata) {
740741 if ( ! cdata . length ) return ;
741742
742743 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 ;
745747
746748 // we may have more subplots than initialized data due to Axes.getSubplots method
747749 if ( ! scene ) return ;
@@ -782,6 +784,7 @@ function plot(container, subplot, cdata) {
782784 scene . fill2d = createLine ( regl ) ;
783785 }
784786
787+ // update main marker options
785788 if ( scene . line2d ) {
786789 scene . line2d . update ( scene . lineOptions ) ;
787790 }
@@ -790,13 +793,7 @@ function plot(container, subplot, cdata) {
790793 scene . error2d . update ( errorBatch ) ;
791794 }
792795 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 ) ;
800797 }
801798 // fill requires linked traces, so we generate it's positions here
802799 if ( scene . fill2d ) {
@@ -886,17 +883,77 @@ function plot(container, subplot, cdata) {
886883
887884 scene . fill2d . update ( scene . fillOptions ) ;
888885 }
889- }
890886
891- // make sure selection layer is initialized if we require selection
892- var dragmode = layout . dragmode ;
893887
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 ) ;
897953 }
898954 }
899955
956+
900957 // provide viewport and range
901958 var vpRange = cdata . map ( function ( cdscatter ) {
902959 if ( ! cdscatter || ! cdscatter [ 0 ] || ! cdscatter [ 0 ] . trace ) return ;
@@ -925,41 +982,6 @@ function plot(container, subplot, cdata) {
925982 ] ;
926983
927984 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-
963985 // precalculate px coords since we are not going to pan during select
964986 var xpx = Array ( stash . count ) , ypx = Array ( stash . count ) ;
965987 for ( i = 0 ; i < stash . count ; i ++ ) {
@@ -1193,18 +1215,18 @@ function selectPoints(searchInfo, polygon) {
11931215 }
11941216 }
11951217 else {
1196- unels = Array ( stash . count ) ;
1197- for ( i = 0 ; i < stash . count ; i ++ ) {
1198- unels [ i ] = i ;
1199- }
1218+ unels = arrayRange ( stash . count ) ;
12001219 }
12011220
1202- // create selection style once we have something selected
1221+ // make sure selectBatch is created
12031222 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
12061227 scene . scatter2d . update ( scene . unselectedOptions ) ;
12071228 }
1229+
12081230 scene . selectBatch [ stash . index ] = els ;
12091231 scene . unselectBatch [ stash . index ] = unels ;
12101232
0 commit comments