Skip to content

Commit

Permalink
Merge pull request #2527 from plotly/splom-zoom-perf
Browse files Browse the repository at this point in the history
Splom zoom perf
  • Loading branch information
etpinard committed Apr 11, 2018
2 parents 062d4a3 + f7d637d commit 978a70e
Show file tree
Hide file tree
Showing 28 changed files with 540 additions and 347 deletions.
6 changes: 5 additions & 1 deletion src/components/shapes/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ function draw(gd) {
// Remove previous shapes before drawing new in shapes in fullLayout.shapes
fullLayout._shapeUpperLayer.selectAll('path').remove();
fullLayout._shapeLowerLayer.selectAll('path').remove();
fullLayout._shapeSubplotLayers.selectAll('path').remove();

for(var k in fullLayout._plots) {
var shapelayer = fullLayout._plots[k].shapelayer;
if(shapelayer) shapelayer.selectAll('path').remove();
}

for(var i = 0; i < fullLayout.shapes.length; i++) {
if(fullLayout.shapes[i].visible) {
Expand Down
3 changes: 2 additions & 1 deletion src/plot_api/edit_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var layoutOpts = {
valType: 'flaglist',
extras: ['none'],
flags: [
'calc', 'calcIfAutorange', 'plot', 'legend', 'ticks', 'margins',
'calc', 'calcIfAutorange', 'plot', 'legend', 'ticks', 'axrange', 'margins',
'layoutstyle', 'modebar', 'camera', 'arraydraw'
],
description: [
Expand All @@ -48,6 +48,7 @@ var layoutOpts = {
'*legend* only redraws the legend.',
'*ticks* only redraws axis ticks, labels, and gridlines.',
'*margins* recomputes ticklabel automargins.',
'*axrange* minimal sequence when updating axis ranges.',
'*layoutstyle* reapplies global and SVG cartesian axis styles.',
'*modebar* just updates the modebar.',
'*camera* just updates the camera settings for gl3d scenes.',
Expand Down
164 changes: 58 additions & 106 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,21 @@ var Registry = require('../registry');
var PlotSchema = require('./plot_schema');
var Plots = require('../plots/plots');
var Polar = require('../plots/polar/legacy');
var initInteractions = require('../plots/cartesian/graph_interact');

var Axes = require('../plots/cartesian/axes');
var Drawing = require('../components/drawing');
var Color = require('../components/color');
var initInteractions = require('../plots/cartesian/graph_interact').initInteractions;
var xmlnsNamespaces = require('../constants/xmlns_namespaces');
var svgTextUtils = require('../lib/svg_text_utils');
var clearGlCanvases = require('../lib/clear_gl_canvases');

var defaultConfig = require('./plot_config');
var manageArrays = require('./manage_arrays');
var helpers = require('./helpers');
var subroutines = require('./subroutines');
var editTypes = require('./edit_types');

var cartesianConstants = require('../plots/cartesian/constants');
var axisConstraints = require('../plots/cartesian/constraints');
var enforceAxisConstraints = axisConstraints.enforce;
var cleanAxisConstraints = axisConstraints.clean;
var doAutoRange = require('../plots/cartesian/autorange').doAutoRange;
var AX_NAME_PATTERN = require('../plots/cartesian/constants').AX_NAME_PATTERN;

var numericNameWarningCount = 0;
var numericNameWarningCountLimit = 5;
Expand Down Expand Up @@ -331,15 +326,7 @@ exports.plot = function(gd, data, layout, config) {
function doAutoRangeAndConstraints() {
if(gd._transitioning) return;

var axList = Axes.list(gd, '', true);
for(var i = 0; i < axList.length; i++) {
var ax = axList[i];
cleanAxisConstraints(gd, ax);

doAutoRange(ax);
}

enforceAxisConstraints(gd);
subroutines.doAutoRangeAndConstraints(gd);

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

// Now plot the data
function drawData() {
var calcdata = gd.calcdata,
i,
rangesliderContainers = fullLayout._infolayer.selectAll('g.rangeslider-container');

// in case of traces that were heatmaps or contour maps
// previously, remove them and their colorbars explicitly
for(i = 0; i < calcdata.length; i++) {
var trace = calcdata[i][0].trace,
isVisible = (trace.visible === true),
uid = trace.uid;

if(!isVisible || !Registry.traceIs(trace, '2dMap')) {
var query = (
'.hm' + uid +
',.contour' + uid +
',#clip' + uid
);

fullLayout._paper
.selectAll(query)
.remove();

rangesliderContainers
.selectAll(query)
.remove();
}

if(!isVisible || !trace._module.colorbar) {
fullLayout._infolayer.selectAll('.cb' + uid).remove();
}
}

// TODO does this break or slow down parcoords??
clearGlCanvases(gd);

// loop over the base plot modules present on graph
var basePlotModules = fullLayout._basePlotModules;
for(i = 0; i < basePlotModules.length; i++) {
basePlotModules[i].plot(gd);
}

// keep reference to shape layers in subplots
var layerSubplot = fullLayout._paper.selectAll('.layer-subplot');
fullLayout._shapeSubplotLayers = layerSubplot.selectAll('.shapelayer');

// styling separate from drawing
Plots.style(gd);

// show annotations and shapes
Registry.getComponentMethod('shapes', 'draw')(gd);
Registry.getComponentMethod('annotations', 'draw')(gd);

// source links
Plots.addLinks(gd);

// Mark the first render as complete
fullLayout._replotting = false;

return Plots.previousPromises(gd);
}

// An initial paint must be completed before these components can be
// correctly sized and the whole plot re-margined. fullLayout._replotting must
// be set to false before these will work properly.
function finalDraw() {
Registry.getComponentMethod('shapes', 'draw')(gd);
Registry.getComponentMethod('images', 'draw')(gd);
Registry.getComponentMethod('annotations', 'draw')(gd);
Registry.getComponentMethod('legend', 'draw')(gd);
Registry.getComponentMethod('rangeslider', 'draw')(gd);
Registry.getComponentMethod('rangeselector', 'draw')(gd);
Registry.getComponentMethod('sliders', 'draw')(gd);
Registry.getComponentMethod('updatemenus', 'draw')(gd);
}

var seq = [
Plots.previousPromises,
addFrames,
Expand All @@ -439,9 +349,10 @@ exports.plot = function(gd, data, layout, config) {
seq.push(subroutines.layoutStyles);
if(hasCartesian) seq.push(drawAxes);
seq.push(
drawData,
finalDraw,
subroutines.drawData,
subroutines.finalDraw,
initInteractions,
Plots.addLinks,
Plots.rehover,
Plots.previousPromises
);
Expand Down Expand Up @@ -1385,8 +1296,8 @@ exports.restyle = function restyle(gd, astr, val, _traces) {

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

var specs = _restyle(gd, aobj, traces),
flags = specs.flags;
var specs = _restyle(gd, aobj, traces);
var flags = specs.flags;

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

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

var specs = _relayout(gd, aobj),
flags = specs.flags;
var specs = _relayout(gd, aobj);
var flags = specs.flags;

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

if(flags.legend) seq.push(subroutines.doLegend);
if(flags.layoutstyle) seq.push(subroutines.layoutStyles);

if(flags.axrange) {
// N.B. leave as sequence of subroutines (for now) instead of
// subroutine of its own so that finalDraw always gets
// executed after drawData
seq.push(
// TODO
// no test fail when commenting out doAutoRangeAndConstraints,
// but I think we do need this (maybe just the enforce part?)
// Am I right?
// More info in:
// https://github.com/plotly/plotly.js/issues/2540
subroutines.doAutoRangeAndConstraints,
// TODO
// can target specific axes,
// do not have to redraw all axes here
// See:
// https://github.com/plotly/plotly.js/issues/2547
subroutines.doTicksRelayout,
subroutines.drawData,
subroutines.finalDraw
);
}

if(flags.ticks) seq.push(subroutines.doTicksRelayout);
if(flags.modebar) seq.push(subroutines.doModeBar);
if(flags.camera) seq.push(subroutines.doCamera);
Expand Down Expand Up @@ -1992,7 +1927,7 @@ function _relayout(gd, aobj) {
}
Lib.nestedProperty(fullLayout, ptrunk + '._inputRange').set(null);
}
else if(pleaf.match(cartesianConstants.AX_NAME_PATTERN)) {
else if(pleaf.match(AX_NAME_PATTERN)) {
var fullProp = Lib.nestedProperty(fullLayout, ai).get(),
newType = (vi || {}).type;

Expand Down Expand Up @@ -2045,8 +1980,9 @@ function _relayout(gd, aobj) {
if(checkForAutorange && (refAutorange(gd, objToAutorange, 'x') || refAutorange(gd, objToAutorange, 'y'))) {
flags.calc = true;
}
else editTypes.update(flags, updateValObject);

else {
editTypes.update(flags, updateValObject);
}

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

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

var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces),
restyleFlags = restyleSpecs.flags;
var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces);
var restyleFlags = restyleSpecs.flags;

var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate)),
relayoutFlags = relayoutSpecs.flags;
var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate));
var relayoutFlags = relayoutSpecs.flags;

// clear calcdata and/or axis types if required
if(restyleFlags.clearCalc || relayoutFlags.calc) gd.calcdata = undefined;
Expand Down Expand Up @@ -2236,6 +2172,14 @@ exports.update = function update(gd, traceUpdate, layoutUpdate, _traces) {
if(restyleFlags.colorbars) seq.push(subroutines.doColorBars);
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
if(relayoutFlags.axrange) {
seq.push(
subroutines.doAutoRangeAndConstraints,
subroutines.doTicksRelayout,
subroutines.drawData,
subroutines.finalDraw
);
}
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
if(relayoutFlags.camera) seq.push(subroutines.doCamera);
Expand Down Expand Up @@ -2388,6 +2332,14 @@ exports.react = function(gd, data, layout, config) {
if(restyleFlags.colorbars) seq.push(subroutines.doColorBars);
if(relayoutFlags.legend) seq.push(subroutines.doLegend);
if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles);
if(relayoutFlags.axrange) {
seq.push(
subroutines.doAutoRangeAndConstraints,
subroutines.doTicksRelayout,
subroutines.drawData,
subroutines.finalDraw
);
}
if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout);
if(relayoutFlags.modebar) seq.push(subroutines.doModeBar);
if(relayoutFlags.camera) seq.push(subroutines.doCamera);
Expand Down
Loading

0 comments on commit 978a70e

Please sign in to comment.