Skip to content

Commit b47aa96

Browse files
committed
try to remove lsInner dependence in Axes.drawOne
- add Axes.getAxisLinePosition and wrappers getAxisMirrorLinePosition and getAxisSubplotLinePositions wrappers and remove ax._mainLinePosition, ax._mainMirrorPosition and ax._linepositions stashes - replace ax._lw by Drawing.crispRound calls - replace ax._gw by Drawing.crispRound call - Axes.getAxisLinePosition in graph_interact (!)
1 parent c5ddc28 commit b47aa96

File tree

3 files changed

+107
-111
lines changed

3 files changed

+107
-111
lines changed

src/plot_api/subroutines.js

+28-70
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ function lsInner(gd) {
5555
var gs = fullLayout._size;
5656
var pad = gs.p;
5757
var axList = Axes.list(gd, '', true);
58-
var i, subplot, plotinfo, ax, xa, ya;
5958

6059
fullLayout._paperdiv.style({
6160
width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px',
@@ -74,43 +73,7 @@ function lsInner(gd) {
7473
if(!fullLayout._has('cartesian')) {
7574
return Plots.previousPromises(gd);
7675
}
77-
78-
function getLinePosition(ax, counterAx, side) {
79-
var lwHalf = ax._lw / 2;
80-
81-
if(ax._id.charAt(0) === 'x') {
82-
if(!counterAx) return gs.t + gs.h * (1 - (ax.position || 0)) + (lwHalf % 1);
83-
else if(side === 'top') return counterAx._offset - pad - lwHalf;
84-
return counterAx._offset + counterAx._length + pad + lwHalf;
85-
}
86-
87-
if(!counterAx) return gs.l + gs.w * (ax.position || 0) + (lwHalf % 1);
88-
else if(side === 'right') return counterAx._offset + counterAx._length + pad + lwHalf;
89-
return counterAx._offset - pad - lwHalf;
90-
}
91-
92-
// some preparation of axis position info
93-
for(i = 0; i < axList.length; i++) {
94-
ax = axList[i];
95-
96-
var counterAx = ax._anchorAxis;
97-
98-
// clear axis line positions, to be set in the subplot loop below
99-
ax._linepositions = {};
100-
101-
// stash crispRounded linewidth so we don't need to pass gd all over the place
102-
ax._lw = Drawing.crispRound(gd, ax.linewidth, 1);
103-
104-
// figure out the main axis line and main mirror line position.
105-
// it's easier to follow the logic if we handle these separately from
106-
// ax._linepositions, which are only used by mirror=allticks
107-
// for non-main-subplot ticks, and mirror=all(ticks)? for zero line
108-
// hiding logic
109-
ax._mainLinePosition = getLinePosition(ax, counterAx, ax.side);
110-
ax._mainMirrorPosition = (ax.mirror && counterAx) ?
111-
getLinePosition(ax, counterAx,
112-
alignmentConstants.OPPOSITE_SIDE[ax.side]) : null;
113-
}
76+
var i, subplot, plotinfo, xa, ya;
11477

11578
// figure out which backgrounds we need to draw,
11679
// and in which layers to put them
@@ -253,9 +216,10 @@ function lsInner(gd) {
253216

254217
function mainPath(ax, pathFn, pathFnFree) {
255218
if(!ax.showline || subplot !== ax._mainSubplot) return '';
256-
if(!ax._anchorAxis) return pathFnFree(ax._mainLinePosition);
257-
var out = pathFn(ax._mainLinePosition);
258-
if(ax.mirror) out += pathFn(ax._mainMirrorPosition);
219+
var mainLinePosition = Axes.getAxisLinePosition(gd, ax);
220+
if(!ax._anchorAxis) return pathFnFree(mainLinePosition);
221+
var out = pathFn(mainLinePosition);
222+
if(ax.mirror) out += pathFn(Axes.getAxisMirrorLinePosition(gd, ax));
259223
return out;
260224
}
261225

@@ -280,30 +244,25 @@ function lsInner(gd) {
280244
*/
281245
var xPath = 'M0,0';
282246
if(shouldShowLinesOrTicks(xa, subplot)) {
283-
leftYLineWidth = findCounterAxisLineWidth(xa, 'left', ya, axList);
247+
leftYLineWidth = findCounterAxisLineWidth(gd, xa, 'left', ya, axList);
284248
xLinesXLeft = xa._offset - (leftYLineWidth ? (pad + leftYLineWidth) : 0);
285-
rightYLineWidth = findCounterAxisLineWidth(xa, 'right', ya, axList);
249+
rightYLineWidth = findCounterAxisLineWidth(gd, xa, 'right', ya, axList);
286250
xLinesXRight = xa._offset + xa._length + (rightYLineWidth ? (pad + rightYLineWidth) : 0);
287-
xLinesYBottom = getLinePosition(xa, ya, 'bottom');
288-
xLinesYTop = getLinePosition(xa, ya, 'top');
251+
xLinesYBottom = Axes.getAxisLinePosition(gd, xa, ya, 'bottom');
252+
xLinesYTop = Axes.getAxisLinePosition(gd, xa, ya, 'top');
289253

290254
// save axis line positions for extra ticks to reference
291255
// each subplot that gets ticks from "allticks" gets an entry:
292256
// [left or bottom, right or top]
293257
extraSubplot = (!xa._anchorAxis || subplot !== xa._mainSubplot);
294-
if(extraSubplot && (xa.mirror === 'allticks' || xa.mirror === 'all')) {
295-
xa._linepositions[subplot] = [xLinesYBottom, xLinesYTop];
296-
}
297-
298258
xPath = mainPath(xa, xLinePath, xLinePathFree);
299259
if(extraSubplot && xa.showline && (xa.mirror === 'all' || xa.mirror === 'allticks')) {
300260
xPath += xLinePath(xLinesYBottom) + xLinePath(xLinesYTop);
301261
}
302262

303263
plotinfo.xlines
304-
.style('stroke-width', xa._lw + 'px')
305-
.call(Color.stroke, xa.showline ?
306-
xa.linecolor : 'rgba(0,0,0,0)');
264+
.style('stroke-width', crispRoundLineWidth(gd, xa) + 'px')
265+
.call(Color.stroke, xa.showline ? xa.linecolor : 'rgba(0,0,0,0)');
307266
}
308267
plotinfo.xlines.attr('d', xPath);
309268

@@ -320,27 +279,22 @@ function lsInner(gd) {
320279
*/
321280
var yPath = 'M0,0';
322281
if(shouldShowLinesOrTicks(ya, subplot)) {
323-
connectYBottom = findCounterAxisLineWidth(ya, 'bottom', xa, axList);
282+
connectYBottom = findCounterAxisLineWidth(gd, ya, 'bottom', xa, axList);
324283
yLinesYBottom = ya._offset + ya._length + (connectYBottom ? pad : 0);
325-
connectYTop = findCounterAxisLineWidth(ya, 'top', xa, axList);
284+
connectYTop = findCounterAxisLineWidth(gd, ya, 'top', xa, axList);
326285
yLinesYTop = ya._offset - (connectYTop ? pad : 0);
327-
yLinesXLeft = getLinePosition(ya, xa, 'left');
328-
yLinesXRight = getLinePosition(ya, xa, 'right');
286+
yLinesXLeft = Axes.getAxisLinePosition(gd, ya, xa, 'left');
287+
yLinesXRight = Axes.getAxisLinePosition(gd, ya, xa, 'right');
329288

330289
extraSubplot = (!ya._anchorAxis || subplot !== ya._mainSubplot);
331-
if(extraSubplot && (ya.mirror === 'allticks' || ya.mirror === 'all')) {
332-
ya._linepositions[subplot] = [yLinesXLeft, yLinesXRight];
333-
}
334-
335290
yPath = mainPath(ya, yLinePath, yLinePathFree);
336291
if(extraSubplot && ya.showline && (ya.mirror === 'all' || ya.mirror === 'allticks')) {
337292
yPath += yLinePath(yLinesXLeft) + yLinePath(yLinesXRight);
338293
}
339294

340295
plotinfo.ylines
341-
.style('stroke-width', ya._lw + 'px')
342-
.call(Color.stroke, ya.showline ?
343-
ya.linecolor : 'rgba(0,0,0,0)');
296+
.style('stroke-width', crispRoundLineWidth(gd, ya) + 'px')
297+
.call(Color.stroke, ya.showline ? ya.linecolor : 'rgba(0,0,0,0)');
344298
}
345299
plotinfo.ylines.attr('d', yPath);
346300
}
@@ -360,9 +314,9 @@ function shouldShowLinesOrTicks(ax, subplot) {
360314
* It's assumed that counterAx is known to overlay the subplot we're working on
361315
* but it may not be its main axis.
362316
*/
363-
function shouldShowLineThisSide(ax, side, counterAx) {
317+
function shouldShowLineThisSide(gd, ax, side, counterAx) {
364318
// does counterAx get a line at all?
365-
if(!counterAx.showline || !counterAx._lw) return false;
319+
if(!counterAx.showline || !crispRoundLineWidth(gd, ax)) return false;
366320

367321
// are we drawing *all* lines for counterAx?
368322
if(counterAx.mirror === 'all' || counterAx.mirror === 'allticks') return true;
@@ -388,19 +342,23 @@ function shouldShowLineThisSide(ax, side, counterAx) {
388342
* then at all other potential counteraxes on or overlaying this subplot.
389343
* Take the line width from the first one that has a line.
390344
*/
391-
function findCounterAxisLineWidth(ax, side, counterAx, axList) {
392-
if(shouldShowLineThisSide(ax, side, counterAx)) {
393-
return counterAx._lw;
345+
function findCounterAxisLineWidth(gd, ax, side, counterAx, axList) {
346+
if(shouldShowLineThisSide(gd, ax, side, counterAx)) {
347+
return crispRoundLineWidth(gd, counterAx);
394348
}
395349
for(var i = 0; i < axList.length; i++) {
396350
var axi = axList[i];
397-
if(axi._mainAxis === counterAx._mainAxis && shouldShowLineThisSide(ax, side, axi)) {
398-
return axi._lw;
351+
if(axi._mainAxis === counterAx._mainAxis && shouldShowLineThisSide(gd, ax, side, axi)) {
352+
return crispRoundLineWidth(gd, axi);
399353
}
400354
}
401355
return 0;
402356
}
403357

358+
function crispRoundLineWidth(gd, ax) {
359+
return Drawing.crispRound(gd, ax.linewidth, 1);
360+
}
361+
404362
exports.drawMainTitle = function(gd) {
405363
var fullLayout = gd._fullLayout;
406364

src/plots/cartesian/axes.js

+76-39
Original file line numberDiff line numberDiff line change
@@ -1643,9 +1643,6 @@ axes.draw = function(gd, arg, opts) {
16431643
* - ax._anchorAxis
16441644
* - ax._subplotsWith
16451645
* - ax._counterDomainMin, ax._counterDomainMax (optionally, from linkSubplots)
1646-
* - ax._mainLinePosition (from lsInner)
1647-
* - ax._mainMirrorPosition
1648-
* - ax._linepositions
16491646
*
16501647
* Fills in:
16511648
* - ax._vals:
@@ -1666,10 +1663,11 @@ axes.drawOne = function(gd, ax, opts) {
16661663
var axId = ax._id;
16671664
var axLetter = axId.charAt(0);
16681665
var counterLetter = axes.counterLetter(axId);
1669-
var mainLinePosition = ax._mainLinePosition;
1670-
var mainMirrorPosition = ax._mainMirrorPosition;
1666+
var mainLinePosition = axes.getAxisLinePosition(gd, ax);
1667+
var mainMirrorPosition = axes.getAxisMirrorLinePosition(gd, ax);
16711668
var mainPlotinfo = fullLayout._plots[ax._mainSubplot];
16721669
var mainAxLayer = mainPlotinfo[axLetter + 'axislayer'];
1670+
var subplotsWithAx = ax._subplotsWith;
16731671

16741672
var vals = ax._vals = axes.calcTicks(ax);
16751673

@@ -1721,8 +1719,6 @@ axes.drawOne = function(gd, ax, opts) {
17211719
var dividerVals = getDividerVals(ax, vals);
17221720

17231721
if(!fullLayout._hasOnlyLargeSploms) {
1724-
var subplotsWithAx = ax._subplotsWith;
1725-
17261722
// keep track of which subplots (by main counter axis) we've already
17271723
// drawn grids for, so we don't overdraw overlaying subplots
17281724
var finishedGrids = {};
@@ -1757,7 +1753,6 @@ axes.drawOne = function(gd, ax, opts) {
17571753
}
17581754

17591755
var tickSigns = axes.getTickSigns(ax);
1760-
var tickSubplots = [];
17611756

17621757
if(ax.ticks) {
17631758
var mainTickPath = axes.makeTickPath(ax, mainLinePosition, tickSigns[2]);
@@ -1790,26 +1785,18 @@ axes.drawOne = function(gd, ax, opts) {
17901785
path: tickPath,
17911786
transFn: transFn
17921787
});
1793-
1794-
if(ax.mirror === 'allticks') {
1795-
tickSubplots = Object.keys(ax._linepositions || {});
1796-
}
17971788
}
17981789

1799-
for(i = 0; i < tickSubplots.length; i++) {
1800-
sp = tickSubplots[i];
1801-
plotinfo = fullLayout._plots[sp];
1802-
// [bottom or left, top or right], free and main are handled above
1803-
var linepositions = ax._linepositions[sp] || [];
1804-
var spTickPath = axes.makeTickPath(ax, linepositions[0], tickSigns[0]) +
1805-
axes.makeTickPath(ax, linepositions[1], tickSigns[1]);
1806-
1807-
axes.drawTicks(gd, ax, {
1808-
vals: tickVals,
1809-
layer: plotinfo[axLetter + 'axislayer'],
1810-
path: spTickPath,
1811-
transFn: transFn
1812-
});
1790+
for(i = 0; i < subplotsWithAx.length; i++) {
1791+
var lp = getAxisSubplotLinePositions(gd, ax, subplotsWithAx[i]);
1792+
if(lp) {
1793+
axes.drawTicks(gd, ax, {
1794+
vals: tickVals,
1795+
layer: plotinfo[axLetter + 'axislayer'],
1796+
path: axes.makeTickPath(ax, lp[0], tickSigns[0]) + axes.makeTickPath(ax, lp[1], tickSigns[1]),
1797+
transFn: transFn
1798+
});
1799+
}
18131800
}
18141801

18151802
var seq = [];
@@ -2333,12 +2320,10 @@ axes.drawGrid = function(gd, ax, opts) {
23332320
.classed(cls, 1)
23342321
.classed('crisp', opts.crisp !== false);
23352322

2336-
ax._gw = Drawing.crispRound(gd, ax.gridwidth, 1);
2337-
23382323
grid.attr('transform', opts.transFn)
23392324
.attr('d', opts.path)
23402325
.call(Color.stroke, ax.gridcolor || '#ddd')
2341-
.style('stroke-width', ax._gw + 'px');
2326+
.style('stroke-width', Drawing.crispRound(gd, ax.gridwidth, 1) + 'px');
23422327

23432328
if(typeof opts.path === 'function') grid.attr('d', opts.path);
23442329
};
@@ -2352,7 +2337,7 @@ axes.drawGrid = function(gd, ax, opts) {
23522337
* - {boolean} zeroline
23532338
* - {number} zerolinewidth
23542339
* - {string} zerolinecolor
2355-
* - {number (optional)} _gridWidthCrispRound
2340+
* - {number} gridwidth
23562341
* @param {object} opts
23572342
* - {d3 selection} layer
23582343
* - {object} counterAxis (full axis object corresponding to counter axis)
@@ -2384,10 +2369,12 @@ axes.drawZeroLine = function(gd, ax, opts) {
23842369
});
23852370
});
23862371

2372+
var gw = Drawing.crispRound(gd, ax.gridwidth, 1);
2373+
23872374
zl.attr('transform', opts.transFn)
23882375
.attr('d', opts.path)
23892376
.call(Color.stroke, ax.zerolinecolor || Color.defaultLine)
2390-
.style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px');
2377+
.style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, gw || 1) + 'px');
23912378
};
23922379

23932380
/**
@@ -2636,6 +2623,56 @@ function drawDividers(gd, ax, opts) {
26362623
.attr('d', opts.path);
26372624
}
26382625

2626+
/**
2627+
* TODO
2628+
*
2629+
* @param {}
2630+
*/
2631+
axes.getAxisLinePosition = function(gd, ax, counterAx, side) {
2632+
counterAx = counterAx || ax._anchorAxis;
2633+
side = side || ax.side;
2634+
2635+
var fullLayout = gd._fullLayout;
2636+
var gs = fullLayout._size;
2637+
var lwHalf = Drawing.crispRound(gd, ax.linewidth, 1) / 2;
2638+
2639+
if(ax._id.charAt(0) === 'x') {
2640+
if(!counterAx) return gs.t + gs.h * (1 - (ax.position || 0)) + (lwHalf % 1);
2641+
else if(side === 'top') return counterAx._offset - gs.p - lwHalf;
2642+
return counterAx._offset + counterAx._length + gs.p + lwHalf;
2643+
}
2644+
2645+
if(!counterAx) return gs.l + gs.w * (ax.position || 0) + (lwHalf % 1);
2646+
else if(side === 'right') return counterAx._offset + counterAx._length + gs.p + lwHalf;
2647+
return counterAx._offset - gs.p - lwHalf;
2648+
};
2649+
2650+
/**
2651+
* TODO
2652+
*
2653+
*/
2654+
axes.getAxisMirrorLinePosition = function(gd, ax) {
2655+
return (ax.mirror && ax._anchorAxis) ?
2656+
axes.getAxisLinePosition(gd, ax, ax._anchorAxis, OPPOSITE_SIDE[ax.side]) :
2657+
null;
2658+
};
2659+
2660+
/**
2661+
* TODO
2662+
*
2663+
*/
2664+
function getAxisSubplotLinePositions(gd, ax, sp) {
2665+
if((!ax._anchorAxis || sp !== ax._mainSubplot) &&
2666+
(ax.mirror === 'allticks' || ax.mirror === 'all')) {
2667+
var axLetter = ax._id.charAt(0);
2668+
return [
2669+
axes.getAxisLinePosition(gd, ax, ax._anchorAxis, {x: 'bottom', y: 'left'}[axLetter]),
2670+
axes.getAxisLinePosition(gd, ax, ax._anchorAxis, {x: 'top', y: 'right'}[axLetter])
2671+
];
2672+
}
2673+
return false;
2674+
}
2675+
26392676
/**
26402677
* Get axis position in px, that is the distance for the graph's
26412678
* top (left) edge for x (y) axes.
@@ -2787,14 +2824,14 @@ function anyCounterAxLineAtZero(gd, ax, counterAxis, rng) {
27872824
return typeof pos2 === 'number' && Math.abs(pos2 - zeroPosition) < tolerance;
27882825
}
27892826

2790-
if(closeEnough(ax2._mainLinePosition) || closeEnough(ax2._mainMirrorPosition)) {
2791-
return true;
2792-
}
2793-
var linePositions = ax2._linepositions || {};
2794-
for(var k in linePositions) {
2795-
if(closeEnough(linePositions[k][0]) || closeEnough(linePositions[k][1])) {
2796-
return true;
2797-
}
2827+
if(closeEnough(axes.getAxisLinePosition(gd, ax)) ||
2828+
closeEnough(axes.getAxisMirrorLinePosition(gd, ax))) return true;
2829+
2830+
var subplotsWithAx = ax._subplotsWith;
2831+
2832+
for(var i = 0; i < subplotsWithAx.length; i++) {
2833+
var lp = getAxisSubplotLinePositions(gd, ax, subplotsWithAx[i]);
2834+
if(lp && (closeEnough(lp[0]) || closeEnough(lp[1]))) return true;
27982835
}
27992836
}
28002837

src/plots/cartesian/graph_interact.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
var d3 = require('d3');
1313

1414
var Fx = require('../../components/fx');
15+
var Axes = require('../../plots/cartesian/axes');
1516
var dragElement = require('../../components/dragelement');
1617
var setCursor = require('../../lib/setcursor');
1718

@@ -107,7 +108,7 @@ exports.initInteractions = function initInteractions(gd) {
107108
// these drag each axis separately
108109
if(subplot === xa._mainSubplot) {
109110
// the y position of the main x axis line
110-
var y0 = xa._mainLinePosition;
111+
var y0 = Axes.getAxisLinePosition(gd, xa);
111112
if(xa.side === 'top') y0 -= DRAGGERSIZE;
112113
makeDragBox(gd, plotinfo, xa._offset + xa._length * 0.1, y0,
113114
xa._length * 0.8, DRAGGERSIZE, '', 'ew');
@@ -119,7 +120,7 @@ exports.initInteractions = function initInteractions(gd) {
119120
// y axis draggers
120121
if(subplot === ya._mainSubplot) {
121122
// the x position of the main y axis line
122-
var x0 = ya._mainLinePosition;
123+
var x0 = Axes.getAxisLinePosition(gd, ya);
123124
if(ya.side !== 'right') x0 -= DRAGGERSIZE;
124125
makeDragBox(gd, plotinfo, x0, ya._offset + ya._length * 0.1,
125126
DRAGGERSIZE, ya._length * 0.8, 'ns', '');

0 commit comments

Comments
 (0)