Skip to content

Commit 25057d6

Browse files
authored
Merge pull request #1444 from plotly/scattergl-lazy-init
scattergl lazy init
2 parents 7a95090 + bb3f850 commit 25057d6

File tree

4 files changed

+134
-108
lines changed

4 files changed

+134
-108
lines changed

src/plots/gl2d/scene2d.js

+6
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,12 @@ proto.updateTraces = function(fullData, calcData) {
494494
this.traces[fullTrace.uid] = traceObj;
495495
}
496496
}
497+
498+
// order object per traces
499+
this.glplot.objects.sort(function(a, b) {
500+
return a._trace.index - b._trace.index;
501+
});
502+
497503
};
498504

499505
proto.emitPointAction = function(nextSelection, eventType) {

src/traces/scattergl/convert.js

+108-97
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,17 @@ function LineWithMarkers(scene, uid) {
4646
this.hoverinfo = 'all';
4747
this.connectgaps = true;
4848

49+
this.index = null;
4950
this.idToIndex = [];
5051
this.bounds = [0, 0, 0, 0];
5152

53+
this.isVisible = false;
5254
this.hasLines = false;
53-
this.lineOptions = {
55+
this.hasErrorX = false;
56+
this.hasErrorY = false;
57+
this.hasMarkers = false;
58+
59+
this.line = this.initObject(createLine, {
5460
positions: new Float64Array(0),
5561
color: [0, 0, 0, 1],
5662
width: 1,
@@ -60,35 +66,26 @@ function LineWithMarkers(scene, uid) {
6066
[0, 0, 0, 1],
6167
[0, 0, 0, 1],
6268
[0, 0, 0, 1]],
63-
dashes: [1]
64-
};
65-
this.line = createLine(scene.glplot, this.lineOptions);
66-
this.line._trace = this;
69+
dashes: [1],
70+
}, 0);
6771

68-
this.hasErrorX = false;
69-
this.errorXOptions = {
72+
this.errorX = this.initObject(createError, {
7073
positions: new Float64Array(0),
7174
errors: new Float64Array(0),
7275
lineWidth: 1,
7376
capSize: 0,
7477
color: [0, 0, 0, 1]
75-
};
76-
this.errorX = createError(scene.glplot, this.errorXOptions);
77-
this.errorX._trace = this;
78+
}, 1);
7879

79-
this.hasErrorY = false;
80-
this.errorYOptions = {
80+
this.errorY = this.initObject(createError, {
8181
positions: new Float64Array(0),
8282
errors: new Float64Array(0),
8383
lineWidth: 1,
8484
capSize: 0,
8585
color: [0, 0, 0, 1]
86-
};
87-
this.errorY = createError(scene.glplot, this.errorYOptions);
88-
this.errorY._trace = this;
86+
}, 2);
8987

90-
this.hasMarkers = false;
91-
this.scatterOptions = {
88+
var scatterOptions0 = {
9289
positions: new Float64Array(0),
9390
sizes: [],
9491
colors: [],
@@ -100,16 +97,44 @@ function LineWithMarkers(scene, uid) {
10097
borderSize: 1,
10198
borderColor: [0, 0, 0, 1]
10299
};
103-
this.scatter = createScatter(scene.glplot, this.scatterOptions);
104-
this.scatter._trace = this;
105-
this.fancyScatter = createFancyScatter(scene.glplot, this.scatterOptions);
106-
this.fancyScatter._trace = this;
107100

108-
this.isVisible = false;
101+
this.scatter = this.initObject(createScatter, scatterOptions0, 3);
102+
this.fancyScatter = this.initObject(createFancyScatter, scatterOptions0, 4);
109103
}
110104

111105
var proto = LineWithMarkers.prototype;
112106

107+
proto.initObject = function(createFn, options, objIndex) {
108+
var _this = this;
109+
var glplot = _this.scene.glplot;
110+
var options0 = Lib.extendFlat({}, options);
111+
var obj = null;
112+
113+
function update() {
114+
if(!obj) {
115+
obj = createFn(glplot, options);
116+
obj._trace = _this;
117+
obj._index = objIndex;
118+
}
119+
obj.update(options);
120+
}
121+
122+
function clear() {
123+
if(obj) obj.update(options0);
124+
}
125+
126+
function dispose() {
127+
if(obj) obj.dispose();
128+
}
129+
130+
return {
131+
options: options,
132+
update: update,
133+
clear: clear,
134+
dispose: dispose
135+
};
136+
};
137+
113138
proto.handlePick = function(pickResult) {
114139
var index = pickResult.pointId;
115140

@@ -226,13 +251,8 @@ function _convertColor(colors, opacities, count) {
226251
return result;
227252
}
228253

229-
/* Order is important here to get the correct laying:
230-
* - lines
231-
* - errorX
232-
* - errorY
233-
* - markers
234-
*/
235254
proto.update = function(options) {
255+
236256
if(options.visible !== true) {
237257
this.isVisible = false;
238258
this.hasLines = false;
@@ -255,7 +275,11 @@ proto.update = function(options) {
255275
this.connectgaps = !!options.connectgaps;
256276

257277
if(!this.isVisible) {
258-
this.clear();
278+
this.line.clear();
279+
this.errorX.clear();
280+
this.errorY.clear();
281+
this.scatter.clear();
282+
this.fancyScatter.clear();
259283
}
260284
else if(this.isFancy(options)) {
261285
this.updateFancy(options);
@@ -264,6 +288,18 @@ proto.update = function(options) {
264288
this.updateFast(options);
265289
}
266290

291+
// sort objects so that order is preserve on updates:
292+
// - lines
293+
// - errorX
294+
// - errorY
295+
// - markers
296+
this.scene.glplot.objects.sort(function(a, b) {
297+
return a._index - b._index;
298+
});
299+
300+
// set trace index so that scene2d can sort object per traces
301+
this.index = options.index;
302+
267303
// not quite on-par with 'scatter', but close enough for now
268304
// does not handle the colorscale case
269305
this.color = getTraceColor(options, {});
@@ -292,22 +328,6 @@ function allFastTypesLikely(a) {
292328
return true;
293329
}
294330

295-
proto.clear = function() {
296-
this.lineOptions.positions = new Float64Array(0);
297-
this.line.update(this.lineOptions);
298-
299-
this.errorXOptions.positions = new Float64Array(0);
300-
this.errorX.update(this.errorXOptions);
301-
302-
this.errorYOptions.positions = new Float64Array(0);
303-
this.errorY.update(this.errorYOptions);
304-
305-
this.scatterOptions.positions = new Float64Array(0);
306-
this.scatterOptions.glyphs = [];
307-
this.scatter.update(this.scatterOptions);
308-
this.fancyScatter.update(this.scatterOptions);
309-
};
310-
311331
proto.updateFast = function(options) {
312332
var x = this.xData = this.pickXData = options.x;
313333
var y = this.yData = this.pickYData = options.y;
@@ -363,34 +383,30 @@ proto.updateFast = function(options) {
363383
var markerSize;
364384

365385
if(this.hasMarkers) {
366-
this.scatterOptions.positions = positions;
386+
this.scatter.options.positions = positions;
367387

368388
var markerColor = str2RGBArray(options.marker.color),
369389
borderColor = str2RGBArray(options.marker.line.color),
370390
opacity = (options.opacity) * (options.marker.opacity);
371391

372392
markerColor[3] *= opacity;
373-
this.scatterOptions.color = markerColor;
393+
this.scatter.options.color = markerColor;
374394

375395
borderColor[3] *= opacity;
376-
this.scatterOptions.borderColor = borderColor;
396+
this.scatter.options.borderColor = borderColor;
377397

378398
markerSize = options.marker.size;
379-
this.scatterOptions.size = markerSize;
380-
this.scatterOptions.borderSize = options.marker.line.width;
399+
this.scatter.options.size = markerSize;
400+
this.scatter.options.borderSize = options.marker.line.width;
381401

382-
this.scatter.update(this.scatterOptions);
402+
this.scatter.update();
383403
}
384404
else {
385-
this.scatterOptions.positions = new Float64Array(0);
386-
this.scatterOptions.glyphs = [];
387-
this.scatter.update(this.scatterOptions);
405+
this.scatter.clear();
388406
}
389407

390408
// turn off fancy scatter plot
391-
this.scatterOptions.positions = new Float64Array(0);
392-
this.scatterOptions.glyphs = [];
393-
this.fancyScatter.update(this.scatterOptions);
409+
this.fancyScatter.clear();
394410

395411
// add item for autorange routine
396412
this.expandAxesFast(bounds, markerSize);
@@ -464,16 +480,16 @@ proto.updateFancy = function(options) {
464480
var sizes;
465481

466482
if(this.hasMarkers) {
467-
this.scatterOptions.positions = positions;
483+
this.scatter.options.positions = positions;
468484

469485
// TODO rewrite convert function so that
470486
// we don't have to loop through the data another time
471487

472-
this.scatterOptions.sizes = new Array(pId);
473-
this.scatterOptions.glyphs = new Array(pId);
474-
this.scatterOptions.borderWidths = new Array(pId);
475-
this.scatterOptions.colors = new Array(pId * 4);
476-
this.scatterOptions.borderColors = new Array(pId * 4);
488+
this.scatter.options.sizes = new Array(pId);
489+
this.scatter.options.glyphs = new Array(pId);
490+
this.scatter.options.borderWidths = new Array(pId);
491+
this.scatter.options.colors = new Array(pId * 4);
492+
this.scatter.options.borderColors = new Array(pId * 4);
477493

478494
var markerSizeFunc = makeBubbleSizeFn(options),
479495
markerOpts = options.marker,
@@ -490,28 +506,24 @@ proto.updateFancy = function(options) {
490506
for(i = 0; i < pId; ++i) {
491507
index = idToIndex[i];
492508

493-
this.scatterOptions.sizes[i] = 4.0 * sizes[index];
494-
this.scatterOptions.glyphs[i] = glyphs[index];
495-
this.scatterOptions.borderWidths[i] = 0.5 * borderWidths[index];
509+
this.scatter.options.sizes[i] = 4.0 * sizes[index];
510+
this.scatter.options.glyphs[i] = glyphs[index];
511+
this.scatter.options.borderWidths[i] = 0.5 * borderWidths[index];
496512

497513
for(j = 0; j < 4; ++j) {
498-
this.scatterOptions.colors[4 * i + j] = colors[4 * index + j];
499-
this.scatterOptions.borderColors[4 * i + j] = borderColors[4 * index + j];
514+
this.scatter.options.colors[4 * i + j] = colors[4 * index + j];
515+
this.scatter.options.borderColors[4 * i + j] = borderColors[4 * index + j];
500516
}
501517
}
502518

503-
this.fancyScatter.update(this.scatterOptions);
519+
this.fancyScatter.update();
504520
}
505521
else {
506-
this.scatterOptions.positions = new Float64Array(0);
507-
this.scatterOptions.glyphs = [];
508-
this.fancyScatter.update(this.scatterOptions);
522+
this.fancyScatter.clear();
509523
}
510524

511525
// turn off fast scatter plot
512-
this.scatterOptions.positions = new Float64Array(0);
513-
this.scatterOptions.glyphs = [];
514-
this.scatter.update(this.scatterOptions);
526+
this.scatter.clear();
515527

516528
// add item for autorange routine
517529
this.expandAxesFancy(x, y, sizes);
@@ -535,61 +547,60 @@ proto.updateLines = function(options, positions) {
535547
}
536548
}
537549

538-
this.lineOptions.positions = linePositions;
550+
this.line.options.positions = linePositions;
539551

540552
var lineColor = convertColor(options.line.color, options.opacity, 1),
541-
lineWidth = Math.round(0.5 * this.lineOptions.width),
553+
lineWidth = Math.round(0.5 * this.line.options.width),
542554
dashes = (DASHES[options.line.dash] || [1]).slice();
543555

544556
for(i = 0; i < dashes.length; ++i) dashes[i] *= lineWidth;
545557

546558
switch(options.fill) {
547559
case 'tozeroy':
548-
this.lineOptions.fill = [false, true, false, false];
560+
this.line.options.fill = [false, true, false, false];
549561
break;
550562
case 'tozerox':
551-
this.lineOptions.fill = [true, false, false, false];
563+
this.line.options.fill = [true, false, false, false];
552564
break;
553565
default:
554-
this.lineOptions.fill = [false, false, false, false];
566+
this.line.options.fill = [false, false, false, false];
555567
break;
556568
}
557569

558570
var fillColor = str2RGBArray(options.fillcolor);
559571

560-
this.lineOptions.color = lineColor;
561-
this.lineOptions.width = 2.0 * options.line.width;
562-
this.lineOptions.dashes = dashes;
563-
this.lineOptions.fillColor = [fillColor, fillColor, fillColor, fillColor];
572+
this.line.options.color = lineColor;
573+
this.line.options.width = 2.0 * options.line.width;
574+
this.line.options.dashes = dashes;
575+
this.line.options.fillColor = [fillColor, fillColor, fillColor, fillColor];
576+
577+
this.line.update();
564578
}
565579
else {
566-
this.lineOptions.positions = new Float64Array(0);
580+
this.line.clear();
567581
}
568-
569-
this.line.update(this.lineOptions);
570582
};
571583

572584
proto.updateError = function(axLetter, options, positions, errors) {
573585
var errorObj = this['error' + axLetter],
574-
errorOptions = options['error_' + axLetter.toLowerCase()],
575-
errorObjOptions = this['error' + axLetter + 'Options'];
586+
errorOptions = options['error_' + axLetter.toLowerCase()];
576587

577588
if(axLetter.toLowerCase() === 'x' && errorOptions.copy_ystyle) {
578589
errorOptions = options.error_y;
579590
}
580591

581592
if(this['hasError' + axLetter]) {
582-
errorObjOptions.positions = positions;
583-
errorObjOptions.errors = errors;
584-
errorObjOptions.capSize = errorOptions.width;
585-
errorObjOptions.lineWidth = errorOptions.thickness / 2; // ballpark rescaling
586-
errorObjOptions.color = convertColor(errorOptions.color, 1, 1);
593+
errorObj.options.positions = positions;
594+
errorObj.options.errors = errors;
595+
errorObj.options.capSize = errorOptions.width;
596+
errorObj.options.lineWidth = errorOptions.thickness / 2; // ballpark rescaling
597+
errorObj.options.color = convertColor(errorOptions.color, 1, 1);
598+
599+
errorObj.update();
587600
}
588601
else {
589-
errorObjOptions.positions = new Float64Array(0);
602+
errorObj.clear();
590603
}
591-
592-
errorObj.update(errorObjOptions);
593604
};
594605

595606
proto.expandAxesFast = function(bounds, markerSize) {

0 commit comments

Comments
 (0)