Skip to content

Commit 71061e5

Browse files
committed
attempt at fixing #3740 and #2958
1 parent 4529fe9 commit 71061e5

File tree

2 files changed

+63
-64
lines changed

2 files changed

+63
-64
lines changed

src/traces/scattergl/index.js

+61-64
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ var createScatter = require('regl-scatter2d');
1212
var createLine = require('regl-line2d');
1313
var createError = require('regl-error2d');
1414
var cluster = require('point-cluster');
15-
var arrayRange = require('array-range');
1615
var Text = require('gl-text');
1716

1817
var 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;
@@ -213,19 +212,20 @@ function sceneUpdate(gd, subplot) {
213212
errorYOptions: [],
214213
textOptions: [],
215214
textSelectedOptions: [],
216-
textUnselectedOptions: []
215+
textUnselectedOptions: [],
216+
// selection batches
217+
selectBatch: [],
218+
unselectBatch: []
217219
};
218220

219221
var initOpts = {
220-
selectBatch: null,
221-
unselectBatch: null,
222222
// regl- component stubs, initialized in dirty plot call
223223
fill2d: false,
224224
scatter2d: false,
225225
error2d: false,
226226
line2d: false,
227227
glText: false,
228-
select2d: null
228+
select2d: false
229229
};
230230

231231
if(!subplot._scene) {
@@ -276,17 +276,22 @@ function sceneUpdate(gd, subplot) {
276276
if(scene.errorXOptions[i]) error2d.draw(i);
277277
if(scene.errorYOptions[i]) error2d.draw(i + count);
278278
}
279-
if(scatter2d && scene.markerOptions[i] && (!selectBatch || !selectBatch[i])) {
280-
scatter2d.draw(i);
279+
if(scatter2d && scene.markerOptions[i]) {
280+
if(unselectBatch[i].length) {
281+
var arg = Lib.repeat([], scene.count);
282+
arg[i] = unselectBatch[i];
283+
scatter2d.draw(arg);
284+
} else {
285+
scatter2d.draw(i);
286+
}
281287
}
282288
if(glText[i] && scene.textOptions[i]) {
283289
glText[i].render();
284290
}
285291
}
286292

287-
if(scatter2d && select2d && selectBatch) {
293+
if(select2d) {
288294
select2d.draw(selectBatch);
289-
scatter2d.draw(unselectBatch);
290295
}
291296

292297
scene.dirty = false;
@@ -350,6 +355,7 @@ function plot(gd, subplot, cdata) {
350355

351356
var fullLayout = gd._fullLayout;
352357
var scene = subplot._scene;
358+
var count = scene.count;
353359
var xaxis = subplot.xaxis;
354360
var yaxis = subplot.yaxis;
355361
var i, j;
@@ -383,28 +389,28 @@ function plot(gd, subplot, cdata) {
383389
scene.fill2d = createLine(regl);
384390
}
385391
if(scene.glText === true) {
386-
scene.glText = new Array(scene.count);
387-
for(i = 0; i < scene.count; i++) {
392+
scene.glText = new Array(count);
393+
for(i = 0; i < count; i++) {
388394
scene.glText[i] = new Text(regl);
389395
}
390396
}
391397

392398
// update main marker options
393399
if(scene.glText) {
394-
if(scene.count > scene.glText.length) {
400+
if(count > scene.glText.length) {
395401
// add gl text marker
396-
var textsToAdd = scene.count - scene.glText.length;
402+
var textsToAdd = count - scene.glText.length;
397403
for(i = 0; i < textsToAdd; i++) {
398404
scene.glText.push(new Text(regl));
399405
}
400-
} else if(scene.count < scene.glText.length) {
406+
} else if(count < scene.glText.length) {
401407
// remove gl text marker
402-
var textsToRemove = scene.glText.length - scene.count;
403-
var removedTexts = scene.glText.splice(scene.count, textsToRemove);
408+
var textsToRemove = scene.glText.length - count;
409+
var removedTexts = scene.glText.splice(count, textsToRemove);
404410
removedTexts.forEach(function(text) { text.destroy(); });
405411
}
406412

407-
for(i = 0; i < scene.count; i++) {
413+
for(i = 0; i < count; i++) {
408414
scene.glText[i].update(scene.textOptions[i]);
409415
}
410416
}
@@ -437,7 +443,7 @@ function plot(gd, subplot, cdata) {
437443
}
438444

439445
// fill requires linked traces, so we generate it's positions here
440-
scene.fillOrder = Lib.repeat(null, scene.count);
446+
scene.fillOrder = Lib.repeat(null, count);
441447
if(scene.fill2d) {
442448
scene.fillOptions = scene.fillOptions.map(function(fillOptions, i) {
443449
var cdscatter = cdata[i];
@@ -556,13 +562,11 @@ function plot(gd, subplot, cdata) {
556562
}
557563

558564
// form batch arrays, and check for selected points
559-
scene.selectBatch = null;
560-
scene.unselectBatch = null;
561565
var dragmode = fullLayout.dragmode;
562566
var selectMode = dragmode === 'lasso' || dragmode === 'select';
563567
var clickSelectEnabled = fullLayout.clickmode.indexOf('select') > -1;
564568

565-
for(i = 0; i < cdata.length; i++) {
569+
for(i = 0; i < count; i++) {
566570
var cd0 = cdata[i][0];
567571
var trace = cd0.trace;
568572
var stash = cd0.t;
@@ -574,11 +578,6 @@ function plot(gd, subplot, cdata) {
574578
if(trace.selectedpoints || selectMode || clickSelectEnabled) {
575579
if(!selectMode) selectMode = true;
576580

577-
if(!scene.selectBatch) {
578-
scene.selectBatch = [];
579-
scene.unselectBatch = [];
580-
}
581-
582581
// regenerate scene batch, if traces number changed during selection
583582
if(trace.selectedpoints) {
584583
var selPts = scene.selectBatch[index] = Lib.selIndices2selPoints(trace);
@@ -610,21 +609,24 @@ function plot(gd, subplot, cdata) {
610609
}
611610
}
612611

613-
614612
if(selectMode) {
615-
// create select2d
613+
// create scatter instance by cloning scatter2d
616614
if(!scene.select2d) {
617-
// create scatter instance by cloning scatter2d
618615
scene.select2d = createScatter(fullLayout._glcanvas.data()[1].regl);
619616
}
620617

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-
}));
618+
// use unselected styles on 'context' canvas
619+
if(scene.scatter2d) {
620+
var unselOpts = new Array(count);
621+
for(i = 0; i < count; i++) {
622+
unselOpts[i] = scene.selectBatch[i].length || scene.unselectBatch[i].length ?
623+
scene.markerUnselectedOptions[i] :
624+
{};
625+
}
626+
scene.scatter2d.update(unselOpts);
626627
}
627628

629+
// use selected style on 'focus' canvas
628630
if(scene.select2d) {
629631
scene.select2d.update(scene.markerOptions);
630632
scene.select2d.update(scene.markerSelectedOptions);
@@ -639,9 +641,9 @@ function plot(gd, subplot, cdata) {
639641
});
640642
}
641643
} else {
644+
// reset 'context' scatter2d opts to base opts,
645+
// thus unsetting markerUnselectedOptions from selection
642646
if(scene.scatter2d) {
643-
// reset scatter2d opts to base opts,
644-
// thus unsetting markerUnselectedOptions from selection
645647
scene.scatter2d.update(scene.markerOptions);
646648
}
647649
}
@@ -871,23 +873,23 @@ function selectPoints(searchInfo, selectionTester) {
871873
var x = stash.x;
872874
var y = stash.y;
873875
var scene = stash._scene;
876+
var index = stash.index;
874877

875878
if(!scene) return selection;
876879

877880
var hasText = subTypes.hasText(trace);
878881
var hasMarkers = subTypes.hasMarkers(trace);
879882
var hasOnlyLines = !hasMarkers && !hasText;
883+
880884
if(trace.visible !== true || hasOnlyLines) return selection;
881885

886+
var els = [];
887+
var unels = [];
888+
882889
// degenerate polygon does not enable selection
883890
// 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;
888891
if(selectionTester !== false && !selectionTester.degenerate) {
889-
els = [], unels = [];
890-
for(i = 0; i < len; i++) {
892+
for(var i = 0; i < len; i++) {
891893
if(selectionTester.contains([stash.xpx[i], stash.ypx[i]], false, i, searchInfo)) {
892894
els.push(i);
893895
selection.push({
@@ -899,32 +901,27 @@ function selectPoints(searchInfo, selectionTester) {
899901
unels.push(i);
900902
}
901903
}
902-
} else {
903-
unels = arrayRange(len);
904904
}
905905

906-
// make sure selectBatch is created
907-
if(!scene.selectBatch) {
908-
scene.selectBatch = [];
909-
scene.unselectBatch = [];
910-
}
906+
if(hasMarkers) {
907+
var scatter2d = scene.scatter2d;
911908

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);
909+
if(!scene.selectBatch[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);
914+
} else if(!els.length && !unels.length) {
915+
// reset to base styles when clearing
916+
var baseOpts = new Array(scene.count);
917+
baseOpts[index] = scene.markerOptions[index];
918+
scatter2d.update.apply(scatter2d, baseOpts);
921919
}
922920
}
923921

924-
scene.selectBatch[stash.index] = els;
925-
scene.unselectBatch[stash.index] = unels;
922+
scene.selectBatch[index] = els;
923+
scene.unselectBatch[index] = unels;
926924

927-
// update text options
928925
if(hasText) {
929926
styleTextSelection(cd);
930927
}
@@ -946,7 +943,7 @@ function styleTextSelection(cd) {
946943
var opts = Lib.extendFlat({}, baseOpts);
947944
var i, j;
948945

949-
if(els && unels) {
946+
if(els.length || unels.length) {
950947
var stc = selOpts.color;
951948
var utc = unselOpts.color;
952949
var base = baseOpts.color;

src/traces/scatterpolargl/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ function plot(gd, subplot, cdata) {
155155
scene.textOptions.push(opts.text);
156156
scene.textSelectedOptions.push(opts.textSel);
157157
scene.textUnselectedOptions.push(opts.textUnsel);
158+
scene.selectBatch.push([]);
159+
scene.unselectBatch.push([]);
158160

159161
stash.x = x;
160162
stash.y = y;

0 commit comments

Comments
 (0)