Skip to content

Commit 69dc0c4

Browse files
committed
DRY and small pref boost for scattergl
- DRY using .plot & .cleear with getViewport helper fn - Dry .plot and .update with repeat helper fn - compute viewport only once per subplot, as opposed to once per trace.
1 parent 1cdc36b commit 69dc0c4

File tree

1 file changed

+71
-79
lines changed

1 file changed

+71
-79
lines changed

src/traces/scattergl/index.js

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,17 @@ function calc(gd, trace) {
122122
scene.textOptions.push(opts.text);
123123
scene.textSelectedOptions.push(opts.textSel);
124124
scene.textUnselectedOptions.push(opts.textUnsel);
125-
scene.count++;
126125

127126
// stash scene ref
128127
stash._scene = scene;
129-
stash.index = scene.count - 1;
128+
stash.index = scene.count;
130129
stash.x = x;
131130
stash.y = y;
132131
stash.positions = positions;
133132
stash.count = count;
134133

134+
scene.count++;
135+
135136
gd.firstscatter = false;
136137
return [{x: false, y: false, t: stash, trace: trace}];
137138
}
@@ -230,19 +231,16 @@ function sceneUpdate(gd, subplot) {
230231

231232
// apply new option to all regl components (used on drag)
232233
scene.update = function update(opt) {
233-
var i;
234-
var opts = new Array(scene.count);
235-
for(i = 0; i < scene.count; i++) {
236-
opts[i] = opt;
237-
}
234+
var opts = repeat(opt, scene.count);
235+
238236
if(scene.fill2d) scene.fill2d.update(opts);
239237
if(scene.scatter2d) scene.scatter2d.update(opts);
240238
if(scene.line2d) scene.line2d.update(opts);
241239
if(scene.error2d) scene.error2d.update(opts.concat(opts));
242240
if(scene.select2d) scene.select2d.update(opts);
243241
if(scene.glText) {
244-
for(i = 0; i < scene.count; i++) {
245-
scene.glText[i].update(opts[i]);
242+
for(var i = 0; i < scene.count; i++) {
243+
scene.glText[i].update(opt);
246244
}
247245
}
248246

@@ -290,18 +288,7 @@ function sceneUpdate(gd, subplot) {
290288
};
291289

292290
scene.clear = function clear() {
293-
var fullLayout = gd._fullLayout;
294-
var vpSize = fullLayout._size;
295-
var width = fullLayout.width;
296-
var height = fullLayout.height;
297-
var xaxis = subplot.xaxis;
298-
var yaxis = subplot.yaxis;
299-
var vp = [
300-
vpSize.l + xaxis.domain[0] * vpSize.w,
301-
vpSize.b + yaxis.domain[0] * vpSize.h,
302-
(width - vpSize.r) - (1 - xaxis.domain[1]) * vpSize.w,
303-
(height - vpSize.t) - (1 - yaxis.domain[1]) * vpSize.h
304-
];
291+
var vp = getViewport(gd._fullLayout, subplot.xaxis, subplot.yaxis);
305292

306293
if(scene.select2d) {
307294
clearViewport(scene.select2d, vp);
@@ -352,6 +339,18 @@ function sceneUpdate(gd, subplot) {
352339
return scene;
353340
}
354341

342+
function getViewport(fullLayout, xaxis, yaxis) {
343+
var gs = fullLayout._size;
344+
var width = fullLayout.width;
345+
var height = fullLayout.height;
346+
return [
347+
gs.l + xaxis.domain[0] * gs.w,
348+
gs.b + yaxis.domain[0] * gs.h,
349+
(width - gs.r) - (1 - xaxis.domain[1]) * gs.w,
350+
(height - gs.t) - (1 - yaxis.domain[1]) * gs.h
351+
];
352+
}
353+
355354
function clearViewport(comp, vp) {
356355
var gl = comp.regl._gl;
357356
gl.enable(gl.SCISSOR_TEST);
@@ -360,22 +359,26 @@ function clearViewport(comp, vp) {
360359
gl.clear(gl.COLOR_BUFFER_BIT);
361360
}
362361

362+
function repeat(opt, cnt) {
363+
var opts = new Array(cnt);
364+
for(var i = 0; i < cnt; i++) {
365+
opts[i] = opt;
366+
}
367+
return opts;
368+
}
369+
363370
function plot(gd, subplot, cdata) {
364371
if(!cdata.length) return;
365372

366-
var i;
367-
368373
var fullLayout = gd._fullLayout;
369-
var scene = cdata[0][0].t._scene;
370-
var dragmode = fullLayout.dragmode;
374+
var scene = subplot._scene;
375+
var xaxis = subplot.xaxis;
376+
var yaxis = subplot.yaxis;
377+
var i, j;
371378

372379
// we may have more subplots than initialized data due to Axes.getSubplots method
373380
if(!scene) return;
374381

375-
var vpSize = fullLayout._size;
376-
var width = fullLayout.width;
377-
var height = fullLayout.height;
378-
379382
var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']);
380383
if(!success) {
381384
scene.init();
@@ -516,38 +519,20 @@ function plot(gd, subplot, cdata) {
516519
}
517520
}
518521

519-
var selectMode = dragmode === 'lasso' || dragmode === 'select';
522+
// form batch arrays, and check for selected points
520523
scene.selectBatch = null;
521524
scene.unselectBatch = null;
525+
var dragmode = fullLayout.dragmode;
526+
var selectMode = dragmode === 'lasso' || dragmode === 'select';
522527

523-
// provide viewport and range
524-
var vpRange = cdata.map(function(cdscatter) {
525-
if(!cdscatter || !cdscatter[0] || !cdscatter[0].trace) return;
526-
var cd = cdscatter[0];
527-
var trace = cd.trace;
528-
var stash = cd.t;
529-
var id = stash.index;
528+
for(i = 0; i < cdata.length; i++) {
529+
var cd0 = cdata[i][0];
530+
var trace = cd0.trace;
531+
var stash = cd0.t;
532+
var index = stash.index;
530533
var x = stash.x;
531534
var y = stash.y;
532535

533-
var xaxis = subplot.xaxis || AxisIDs.getFromId(gd, trace.xaxis || 'x');
534-
var yaxis = subplot.yaxis || AxisIDs.getFromId(gd, trace.yaxis || 'y');
535-
var i;
536-
537-
var range = [
538-
(xaxis._rl || xaxis.range)[0],
539-
(yaxis._rl || yaxis.range)[0],
540-
(xaxis._rl || xaxis.range)[1],
541-
(yaxis._rl || yaxis.range)[1]
542-
];
543-
544-
var viewport = [
545-
vpSize.l + xaxis.domain[0] * vpSize.w,
546-
vpSize.b + yaxis.domain[0] * vpSize.h,
547-
(width - vpSize.r) - (1 - xaxis.domain[1]) * vpSize.w,
548-
(height - vpSize.t) - (1 - yaxis.domain[1]) * vpSize.h
549-
];
550-
551536
if(trace.selectedpoints || selectMode) {
552537
if(!selectMode) selectMode = true;
553538

@@ -558,37 +543,35 @@ function plot(gd, subplot, cdata) {
558543

559544
// regenerate scene batch, if traces number changed during selection
560545
if(trace.selectedpoints) {
561-
var selPts = scene.selectBatch[id] = Lib.selIndices2selPoints(trace);
546+
var selPts = scene.selectBatch[index] = Lib.selIndices2selPoints(trace);
562547

563548
var selDict = {};
564-
for(i = 0; i < selPts.length; i++) {
565-
selDict[selPts[i]] = 1;
549+
for(j = 0; j < selPts.length; j++) {
550+
selDict[selPts[j]] = 1;
566551
}
567552
var unselPts = [];
568-
for(i = 0; i < stash.count; i++) {
569-
if(!selDict[i]) unselPts.push(i);
553+
for(j = 0; j < stash.count; j++) {
554+
if(!selDict[j]) unselPts.push(j);
570555
}
571-
scene.unselectBatch[id] = unselPts;
556+
scene.unselectBatch[index] = unselPts;
572557
}
573558

574559
// precalculate px coords since we are not going to pan during select
575-
var xpx = new Array(stash.count);
576-
var ypx = new Array(stash.count);
577-
for(i = 0; i < stash.count; i++) {
578-
xpx[i] = xaxis.c2p(x[i]);
579-
ypx[i] = yaxis.c2p(y[i]);
560+
// TODO, could do better here e.g.
561+
// - spin that in a webworker
562+
// - compute selection from polygons in data coordinates
563+
// (maybe just for linear axes)
564+
var xpx = stash.xpx = new Array(stash.count);
565+
var ypx = stash.ypx = new Array(stash.count);
566+
for(j = 0; j < stash.count; j++) {
567+
xpx[j] = xaxis.c2p(x[j]);
568+
ypx[j] = yaxis.c2p(y[j]);
580569
}
581-
stash.xpx = xpx;
582-
stash.ypx = ypx;
583-
}
584-
else {
570+
} else {
585571
stash.xpx = stash.ypx = null;
586572
}
573+
}
587574

588-
return trace.visible ?
589-
{viewport: viewport, range: range} :
590-
null;
591-
});
592575

593576
if(selectMode) {
594577
// create select2d
@@ -618,6 +601,19 @@ function plot(gd, subplot, cdata) {
618601
}
619602
}
620603

604+
// provide viewport and range
605+
var vpRange0 = {
606+
viewport: getViewport(fullLayout, xaxis, yaxis),
607+
// TODO do we need those fallbacks?
608+
range: [
609+
(xaxis._rl || xaxis.range)[0],
610+
(yaxis._rl || yaxis.range)[0],
611+
(xaxis._rl || xaxis.range)[1],
612+
(yaxis._rl || yaxis.range)[1]
613+
]
614+
};
615+
var vpRange = repeat(vpRange0, scene.count);
616+
621617
// upload viewport/range data to GPU
622618
if(scene.fill2d) {
623619
scene.fill2d.update(vpRange);
@@ -635,14 +631,10 @@ function plot(gd, subplot, cdata) {
635631
scene.select2d.update(vpRange);
636632
}
637633
if(scene.glText) {
638-
scene.glText.forEach(function(text, i) {
639-
text.update(vpRange[i]);
640-
});
634+
scene.glText.forEach(function(text) { text.update(vpRange0); });
641635
}
642636

643637
scene.draw();
644-
645-
return;
646638
}
647639

648640

0 commit comments

Comments
 (0)