Skip to content

Commit 978a70e

Browse files
authored
Merge pull request #2527 from plotly/splom-zoom-perf
Splom zoom perf
2 parents 062d4a3 + f7d637d commit 978a70e

File tree

28 files changed

+540
-347
lines changed

28 files changed

+540
-347
lines changed

src/components/shapes/draw.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ function draw(gd) {
4242
// Remove previous shapes before drawing new in shapes in fullLayout.shapes
4343
fullLayout._shapeUpperLayer.selectAll('path').remove();
4444
fullLayout._shapeLowerLayer.selectAll('path').remove();
45-
fullLayout._shapeSubplotLayers.selectAll('path').remove();
45+
46+
for(var k in fullLayout._plots) {
47+
var shapelayer = fullLayout._plots[k].shapelayer;
48+
if(shapelayer) shapelayer.selectAll('path').remove();
49+
}
4650

4751
for(var i = 0; i < fullLayout.shapes.length; i++) {
4852
if(fullLayout.shapes[i].visible) {

src/plot_api/edit_types.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var layoutOpts = {
3535
valType: 'flaglist',
3636
extras: ['none'],
3737
flags: [
38-
'calc', 'calcIfAutorange', 'plot', 'legend', 'ticks', 'margins',
38+
'calc', 'calcIfAutorange', 'plot', 'legend', 'ticks', 'axrange', 'margins',
3939
'layoutstyle', 'modebar', 'camera', 'arraydraw'
4040
],
4141
description: [
@@ -48,6 +48,7 @@ var layoutOpts = {
4848
'*legend* only redraws the legend.',
4949
'*ticks* only redraws axis ticks, labels, and gridlines.',
5050
'*margins* recomputes ticklabel automargins.',
51+
'*axrange* minimal sequence when updating axis ranges.',
5152
'*layoutstyle* reapplies global and SVG cartesian axis styles.',
5253
'*modebar* just updates the modebar.',
5354
'*camera* just updates the camera settings for gl3d scenes.',

src/plot_api/plot_api.js

+58-106
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,21 @@ var Registry = require('../registry');
2222
var PlotSchema = require('./plot_schema');
2323
var Plots = require('../plots/plots');
2424
var Polar = require('../plots/polar/legacy');
25-
var initInteractions = require('../plots/cartesian/graph_interact');
2625

2726
var Axes = require('../plots/cartesian/axes');
2827
var Drawing = require('../components/drawing');
2928
var Color = require('../components/color');
29+
var initInteractions = require('../plots/cartesian/graph_interact').initInteractions;
3030
var xmlnsNamespaces = require('../constants/xmlns_namespaces');
3131
var svgTextUtils = require('../lib/svg_text_utils');
32-
var clearGlCanvases = require('../lib/clear_gl_canvases');
3332

3433
var defaultConfig = require('./plot_config');
3534
var manageArrays = require('./manage_arrays');
3635
var helpers = require('./helpers');
3736
var subroutines = require('./subroutines');
3837
var editTypes = require('./edit_types');
3938

40-
var cartesianConstants = require('../plots/cartesian/constants');
41-
var axisConstraints = require('../plots/cartesian/constraints');
42-
var enforceAxisConstraints = axisConstraints.enforce;
43-
var cleanAxisConstraints = axisConstraints.clean;
44-
var doAutoRange = require('../plots/cartesian/autorange').doAutoRange;
39+
var AX_NAME_PATTERN = require('../plots/cartesian/constants').AX_NAME_PATTERN;
4540

4641
var numericNameWarningCount = 0;
4742
var numericNameWarningCountLimit = 5;
@@ -331,15 +326,7 @@ exports.plot = function(gd, data, layout, config) {
331326
function doAutoRangeAndConstraints() {
332327
if(gd._transitioning) return;
333328

334-
var axList = Axes.list(gd, '', true);
335-
for(var i = 0; i < axList.length; i++) {
336-
var ax = axList[i];
337-
cleanAxisConstraints(gd, ax);
338-
339-
doAutoRange(ax);
340-
}
341-
342-
enforceAxisConstraints(gd);
329+
subroutines.doAutoRangeAndConstraints(gd);
343330

344331
// store initial ranges *after* enforcing constraints, otherwise
345332
// we will never look like we're at the initial ranges
@@ -351,83 +338,6 @@ exports.plot = function(gd, data, layout, config) {
351338
return Axes.doTicks(gd, graphWasEmpty ? '' : 'redraw');
352339
}
353340

354-
// Now plot the data
355-
function drawData() {
356-
var calcdata = gd.calcdata,
357-
i,
358-
rangesliderContainers = fullLayout._infolayer.selectAll('g.rangeslider-container');
359-
360-
// in case of traces that were heatmaps or contour maps
361-
// previously, remove them and their colorbars explicitly
362-
for(i = 0; i < calcdata.length; i++) {
363-
var trace = calcdata[i][0].trace,
364-
isVisible = (trace.visible === true),
365-
uid = trace.uid;
366-
367-
if(!isVisible || !Registry.traceIs(trace, '2dMap')) {
368-
var query = (
369-
'.hm' + uid +
370-
',.contour' + uid +
371-
',#clip' + uid
372-
);
373-
374-
fullLayout._paper
375-
.selectAll(query)
376-
.remove();
377-
378-
rangesliderContainers
379-
.selectAll(query)
380-
.remove();
381-
}
382-
383-
if(!isVisible || !trace._module.colorbar) {
384-
fullLayout._infolayer.selectAll('.cb' + uid).remove();
385-
}
386-
}
387-
388-
// TODO does this break or slow down parcoords??
389-
clearGlCanvases(gd);
390-
391-
// loop over the base plot modules present on graph
392-
var basePlotModules = fullLayout._basePlotModules;
393-
for(i = 0; i < basePlotModules.length; i++) {
394-
basePlotModules[i].plot(gd);
395-
}
396-
397-
// keep reference to shape layers in subplots
398-
var layerSubplot = fullLayout._paper.selectAll('.layer-subplot');
399-
fullLayout._shapeSubplotLayers = layerSubplot.selectAll('.shapelayer');
400-
401-
// styling separate from drawing
402-
Plots.style(gd);
403-
404-
// show annotations and shapes
405-
Registry.getComponentMethod('shapes', 'draw')(gd);
406-
Registry.getComponentMethod('annotations', 'draw')(gd);
407-
408-
// source links
409-
Plots.addLinks(gd);
410-
411-
// Mark the first render as complete
412-
fullLayout._replotting = false;
413-
414-
return Plots.previousPromises(gd);
415-
}
416-
417-
// An initial paint must be completed before these components can be
418-
// correctly sized and the whole plot re-margined. fullLayout._replotting must
419-
// be set to false before these will work properly.
420-
function finalDraw() {
421-
Registry.getComponentMethod('shapes', 'draw')(gd);
422-
Registry.getComponentMethod('images', 'draw')(gd);
423-
Registry.getComponentMethod('annotations', 'draw')(gd);
424-
Registry.getComponentMethod('legend', 'draw')(gd);
425-
Registry.getComponentMethod('rangeslider', 'draw')(gd);
426-
Registry.getComponentMethod('rangeselector', 'draw')(gd);
427-
Registry.getComponentMethod('sliders', 'draw')(gd);
428-
Registry.getComponentMethod('updatemenus', 'draw')(gd);
429-
}
430-
431341
var seq = [
432342
Plots.previousPromises,
433343
addFrames,
@@ -439,9 +349,10 @@ exports.plot = function(gd, data, layout, config) {
439349
seq.push(subroutines.layoutStyles);
440350
if(hasCartesian) seq.push(drawAxes);
441351
seq.push(
442-
drawData,
443-
finalDraw,
352+
subroutines.drawData,
353+
subroutines.finalDraw,
444354
initInteractions,
355+
Plots.addLinks,
445356
Plots.rehover,
446357
Plots.previousPromises
447358
);
@@ -1385,8 +1296,8 @@ exports.restyle = function restyle(gd, astr, val, _traces) {
13851296

13861297
var traces = helpers.coerceTraceIndices(gd, _traces);
13871298

1388-
var specs = _restyle(gd, aobj, traces),
1389-
flags = specs.flags;
1299+
var specs = _restyle(gd, aobj, traces);
1300+
var flags = specs.flags;
13901301

13911302
// clear calcdata and/or axis types if required so they get regenerated
13921303
if(flags.clearCalc) gd.calcdata = undefined;
@@ -1750,8 +1661,8 @@ exports.relayout = function relayout(gd, astr, val) {
17501661

17511662
if(Object.keys(aobj).length) gd.changed = true;
17521663

1753-
var specs = _relayout(gd, aobj),
1754-
flags = specs.flags;
1664+
var specs = _relayout(gd, aobj);
1665+
var flags = specs.flags;
17551666

17561667
// clear calcdata if required
17571668
if(flags.calc) gd.calcdata = undefined;
@@ -1772,6 +1683,30 @@ exports.relayout = function relayout(gd, astr, val) {
17721683

17731684
if(flags.legend) seq.push(subroutines.doLegend);
17741685
if(flags.layoutstyle) seq.push(subroutines.layoutStyles);
1686+
1687+
if(flags.axrange) {
1688+
// N.B. leave as sequence of subroutines (for now) instead of
1689+
// subroutine of its own so that finalDraw always gets
1690+
// executed after drawData
1691+
seq.push(
1692+
// TODO
1693+
// no test fail when commenting out doAutoRangeAndConstraints,
1694+
// but I think we do need this (maybe just the enforce part?)
1695+
// Am I right?
1696+
// More info in:
1697+
// https://github.com/plotly/plotly.js/issues/2540
1698+
subroutines.doAutoRangeAndConstraints,
1699+
// TODO
1700+
// can target specific axes,
1701+
// do not have to redraw all axes here
1702+
// See:
1703+
// https://github.com/plotly/plotly.js/issues/2547
1704+
subroutines.doTicksRelayout,
1705+
subroutines.drawData,
1706+
subroutines.finalDraw
1707+
);
1708+
}
1709+
17751710
if(flags.ticks) seq.push(subroutines.doTicksRelayout);
17761711
if(flags.modebar) seq.push(subroutines.doModeBar);
17771712
if(flags.camera) seq.push(subroutines.doCamera);
@@ -1992,7 +1927,7 @@ function _relayout(gd, aobj) {
19921927
}
19931928
Lib.nestedProperty(fullLayout, ptrunk + '._inputRange').set(null);
19941929
}
1995-
else if(pleaf.match(cartesianConstants.AX_NAME_PATTERN)) {
1930+
else if(pleaf.match(AX_NAME_PATTERN)) {
19961931
var fullProp = Lib.nestedProperty(fullLayout, ai).get(),
19971932
newType = (vi || {}).type;
19981933

@@ -2045,8 +1980,9 @@ function _relayout(gd, aobj) {
20451980
if(checkForAutorange && (refAutorange(gd, objToAutorange, 'x') || refAutorange(gd, objToAutorange, 'y'))) {
20461981
flags.calc = true;
20471982
}
2048-
else editTypes.update(flags, updateValObject);
2049-
1983+
else {
1984+
editTypes.update(flags, updateValObject);
1985+
}
20501986

20511987
// prepare the edits object we'll send to applyContainerArrayChanges
20521988
if(!arrayEdits[arrayStr]) arrayEdits[arrayStr] = {};
@@ -2197,11 +2133,11 @@ exports.update = function update(gd, traceUpdate, layoutUpdate, _traces) {
21972133

21982134
var traces = helpers.coerceTraceIndices(gd, _traces);
21992135

2200-
var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces),
2201-
restyleFlags = restyleSpecs.flags;
2136+
var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces);
2137+
var restyleFlags = restyleSpecs.flags;
22022138

2203-
var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate)),
2204-
relayoutFlags = relayoutSpecs.flags;
2139+
var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate));
2140+
var relayoutFlags = relayoutSpecs.flags;
22052141

22062142
// clear calcdata and/or axis types if required
22072143
if(restyleFlags.clearCalc || relayoutFlags.calc) gd.calcdata = undefined;
@@ -2236,6 +2172,14 @@ exports.update = function update(gd, traceUpdate, layoutUpdate, _traces) {
22362172
if(restyleFlags.colorbars) seq.push(subroutines.doColorBars);
22372173
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
22382174
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
2175+
if(relayoutFlags.axrange) {
2176+
seq.push(
2177+
subroutines.doAutoRangeAndConstraints,
2178+
subroutines.doTicksRelayout,
2179+
subroutines.drawData,
2180+
subroutines.finalDraw
2181+
);
2182+
}
22392183
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
22402184
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
22412185
if(relayoutFlags.camera) seq.push(subroutines.doCamera);
@@ -2388,6 +2332,14 @@ exports.react = function(gd, data, layout, config) {
23882332
if(restyleFlags.colorbars) seq.push(subroutines.doColorBars);
23892333
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
23902334
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
2335+
if(relayoutFlags.axrange) {
2336+
seq.push(
2337+
subroutines.doAutoRangeAndConstraints,
2338+
subroutines.doTicksRelayout,
2339+
subroutines.drawData,
2340+
subroutines.finalDraw
2341+
);
2342+
}
23912343
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
23922344
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
23932345
if(relayoutFlags.camera) seq.push(subroutines.doCamera);

0 commit comments

Comments
 (0)