From 928ff6dc7f6af328d9b1f28b6a7d545fd347e6c2 Mon Sep 17 00:00:00 2001 From: etienne Date: Mon, 19 Mar 2018 16:18:22 -0400 Subject: [PATCH 1/6] do not try to clear ax layers on first render - this can speed up Axes.doTicks by 50ms on 50x50 subplots grids --- src/plot_api/plot_api.js | 2 +- src/plots/cartesian/axes.js | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index d382240bf73..283efa08ce2 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -347,7 +347,7 @@ exports.plot = function(gd, data, layout, config) { // draw ticks, titles, and calculate axis scaling (._b, ._m) function drawAxes() { - return Axes.doTicks(gd, 'redraw'); + return Axes.doTicks(gd, graphWasEmpty ? '' : 'redraw'); } // Now plot the data diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 5b6b766fac9..0f5801dc193 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1539,10 +1539,8 @@ axes.doTicks = function(gd, axid, skipTitle) { return function() { if(!ax._id) return; var axDone = axes.doTicks(gd, ax._id); - if(axid === 'redraw') { - ax._r = ax.range.slice(); - ax._rl = Lib.simpleMap(ax._r, ax.r2l); - } + ax._r = ax.range.slice(); + ax._rl = Lib.simpleMap(ax._r, ax.r2l); return axDone; }; })); From a2c5c3d8a9c6ea54f9525b86719d40aee472014e Mon Sep 17 00:00:00 2001 From: etienne Date: Tue, 20 Mar 2018 11:11:10 -0400 Subject: [PATCH 2/6] use ensureSingle in plot bg lsInner routine --- src/plot_api/subroutines.js | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 8a883cf5d89..9c4b322b3e9 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -124,31 +124,20 @@ exports.lsInner = function(gd) { var xDomain = plotinfo.xaxis.domain; var yDomain = plotinfo.yaxis.domain; - var plotgroupBgData = []; + var plotgroup = plotinfo.plotgroup; + var plotgroupBg; if(overlappingDomain(xDomain, yDomain, lowerDomains)) { - plotgroupBgData = [0]; - } - else { + var pgNode = plotgroup.node(); + plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); + pgNode.insertBefore(plotgroupBg.node(), pgNode.childNodes[0]); + } else { + plotgroupBg = plotgroup.select('rect,bg'); + if(plotgroupBg.size()) plotgroupBg.remove(); + lowerBackgroundIDs.push(subplot); lowerDomains.push([xDomain, yDomain]); } - - // create the plot group backgrounds now, since - // they're all independent selections - var plotgroupBg = plotinfo.plotgroup.selectAll('.bg') - .data(plotgroupBgData); - - plotgroupBg.enter().append('rect') - .classed('bg', true); - - plotgroupBg.exit().remove(); - - plotgroupBg.each(function() { - plotinfo.bg = plotgroupBg; - var pgNode = plotinfo.plotgroup.node(); - pgNode.insertBefore(this, pgNode.childNodes[0]); - }); }); // now create all the lower-layer backgrounds at once now that From 49177a2a4aae87ad78ca67c0a313e14e7afe3c07 Mon Sep 17 00:00:00 2001 From: etienne Date: Tue, 20 Mar 2018 11:11:43 -0400 Subject: [PATCH 3/6] lint in axes.js --- src/plots/cartesian/axes.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 0f5801dc193..a7aae8d4ca0 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1550,21 +1550,21 @@ axes.doTicks = function(gd, axid, skipTitle) { // set scaling to pixels ax.setScale(); - var axLetter = axid.charAt(0), - counterLetter = axes.counterLetter(axid), - vals = axes.calcTicks(ax), - datafn = function(d) { return [d.text, d.x, ax.mirror, d.font, d.fontSize, d.fontColor].join('_'); }, - tcls = axid + 'tick', - gcls = axid + 'grid', - zcls = axid + 'zl', - pad = (ax.linewidth || 1) / 2, - labelStandoff = (ax.ticks === 'outside' ? ax.ticklen : 0), - labelShift = 0, - gridWidth = Drawing.crispRound(gd, ax.gridwidth, 1), - zeroLineWidth = Drawing.crispRound(gd, ax.zerolinewidth, gridWidth), - tickWidth = Drawing.crispRound(gd, ax.tickwidth, 1), - sides, transfn, tickpathfn, subplots, - i; + var axLetter = axid.charAt(0); + var counterLetter = axes.counterLetter(axid); + var vals = axes.calcTicks(ax); + var datafn = function(d) { return [d.text, d.x, ax.mirror, d.font, d.fontSize, d.fontColor].join('_'); }; + var tcls = axid + 'tick'; + var gcls = axid + 'grid'; + var zcls = axid + 'zl'; + var pad = (ax.linewidth || 1) / 2; + var labelStandoff = (ax.ticks === 'outside' ? ax.ticklen : 0); + var labelShift = 0; + var gridWidth = Drawing.crispRound(gd, ax.gridwidth, 1); + var zeroLineWidth = Drawing.crispRound(gd, ax.zerolinewidth, gridWidth); + var tickWidth = Drawing.crispRound(gd, ax.tickwidth, 1); + var sides, transfn, tickpathfn, subplots; + var i; if(ax._counterangle && ax.ticks === 'outside') { var caRad = ax._counterangle * Math.PI / 180; @@ -1614,10 +1614,11 @@ axes.doTicks = function(gd, axid, skipTitle) { Lib.warn('Unrecognized doTicks axis:', axid); return; } - var axside = ax.side || sides[0], + + var axside = ax.side || sides[0]; // which direction do the side[0], side[1], and free ticks go? // then we flip if outside XOR y axis - ticksign = [-1, 1, axside === sides[1] ? 1 : -1]; + var ticksign = [-1, 1, axside === sides[1] ? 1 : -1]; if((ax.ticks !== 'inside') === (axLetter === 'x')) { ticksign = ticksign.map(function(v) { return -v; }); } From 8cf99a6662b341328b92f2b56c3c51fabcbe4771 Mon Sep 17 00:00:00 2001 From: etienne Date: Tue, 20 Mar 2018 11:12:57 -0400 Subject: [PATCH 4/6] stash tickLabels selection in doTicks scope - so that drawTitle() can reuse it - this can speed up doTicks by 200ms at 50x50 subplots --- src/plots/cartesian/axes.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index a7aae8d4ca0..c44db0c9856 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1564,6 +1564,7 @@ axes.doTicks = function(gd, axid, skipTitle) { var zeroLineWidth = Drawing.crispRound(gd, ax.zerolinewidth, gridWidth); var tickWidth = Drawing.crispRound(gd, ax.tickwidth, 1); var sides, transfn, tickpathfn, subplots; + var tickLabels; var i; if(ax._counterangle && ax.ticks === 'outside') { @@ -1646,6 +1647,7 @@ axes.doTicks = function(gd, axid, skipTitle) { function drawTicks(container, tickpath) { var ticks = container.selectAll('path.' + tcls) .data(ax.ticks === 'inside' ? valsClipped : vals, datafn); + if(tickpath && ax.ticks) { ticks.enter().append('path').classed(tcls, 1).classed('ticks', 1) .classed('crisp', 1) @@ -1661,7 +1663,7 @@ axes.doTicks = function(gd, axid, skipTitle) { function drawLabels(container, position) { // tick labels - for now just the main labels. // TODO: mirror labels, esp for subplots - var tickLabels = container.selectAll('g.' + tcls).data(vals, datafn); + tickLabels = container.selectAll('g.' + tcls).data(vals, datafn); if(!isNumeric(position)) { tickLabels.remove(); @@ -2012,14 +2014,12 @@ axes.doTicks = function(gd, axid, skipTitle) { // now this only applies to regular cartesian axes; colorbars and // others ALWAYS call doTicks with skipTitle=true so they can // configure their own titles. - var ax = axisIds.getFromId(gd, axid); // rangeslider takes over a bottom title so drop it here if(ax.rangeslider && ax.rangeslider.visible && ax._boundingBox && ax.side === 'bottom') return; - var avoidSelection = d3.select(gd).selectAll('g.' + axid + 'tick'); var avoid = { - selection: avoidSelection, + selection: tickLabels, side: ax.side }; var axLetter = axid.charAt(0); @@ -2029,8 +2029,8 @@ axes.doTicks = function(gd, axid, skipTitle) { var transform, counterAxis, x, y; - if(avoidSelection.size()) { - var translation = Drawing.getTranslate(avoidSelection.node().parentNode); + if(tickLabels.size()) { + var translation = Drawing.getTranslate(tickLabels.node().parentNode); avoid.offsetLeft = translation.x; avoid.offsetTop = translation.y; } From 5307125ef9655bec0c2e24ba444b3cfc4c1c4f48 Mon Sep 17 00:00:00 2001 From: etienne Date: Mon, 26 Mar 2018 16:41:39 -0400 Subject: [PATCH 5/6] fixup typo in select query & remove neccessary branch --- src/plot_api/subroutines.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 9c4b322b3e9..6227536d273 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -132,9 +132,7 @@ exports.lsInner = function(gd) { plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); pgNode.insertBefore(plotgroupBg.node(), pgNode.childNodes[0]); } else { - plotgroupBg = plotgroup.select('rect,bg'); - if(plotgroupBg.size()) plotgroupBg.remove(); - + plotgroup.select('rect.bg').remove(); lowerBackgroundIDs.push(subplot); lowerDomains.push([xDomain, yDomain]); } From 4059764bf0c6aafcd533bb2f69e8a78f4ab1a6eb Mon Sep 17 00:00:00 2001 From: etienne Date: Mon, 26 Mar 2018 16:53:29 -0400 Subject: [PATCH 6/6] :hocho: unnecessary scoped var --- src/plot_api/subroutines.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 6227536d273..fa74da9e967 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -125,11 +125,10 @@ exports.lsInner = function(gd) { var xDomain = plotinfo.xaxis.domain; var yDomain = plotinfo.yaxis.domain; var plotgroup = plotinfo.plotgroup; - var plotgroupBg; if(overlappingDomain(xDomain, yDomain, lowerDomains)) { var pgNode = plotgroup.node(); - plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); + var plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); pgNode.insertBefore(plotgroupBg.node(), pgNode.childNodes[0]); } else { plotgroup.select('rect.bg').remove();