diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index d22fb26ded8..25685d5e300 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -34,6 +34,11 @@ var ONESEC = constants.ONESEC; var MINUS_SIGN = constants.MINUS_SIGN; var BADNUM = constants.BADNUM; +var ZERO_PATH = { K: 'zeroline' }; +var GRID_PATH = { K: 'gridline', L: 'path' }; +var TICK_PATH = { K: 'tick', L: 'path' }; +var TICK_TEXT = { K: 'tick', L: 'text' }; + var alignmentConstants = require('../../constants/alignment'); var MID_SHIFT = alignmentConstants.MID_SHIFT; var CAP_SHIFT = alignmentConstants.CAP_SHIFT; @@ -1449,7 +1454,7 @@ function formatDate(ax, out, hover, extraPrecision) { ax._prevDateHead = headStr; dateStr += '
' + headStr; } else { - var isInside = (ax.ticklabelposition || '').indexOf('inside') !== -1; + var isInside = insideTicklabelposition(ax); var side = ax._realSide || ax.side; // polar mocks the side of the radial axis if( (!isInside && side === 'top') || @@ -2180,6 +2185,7 @@ axes.drawOne = function(gd, ax, opts) { return axes.drawLabels(gd, ax, { vals: vals, layer: mainAxLayer, + plotinfo: plotinfo, transFn: transTickLabelFn, labelFns: axes.makeLabelFns(ax, mainLinePosition) }); @@ -2798,7 +2804,10 @@ axes.drawTicks = function(gd, ax, opts) { .classed('crisp', opts.crisp !== false) .call(Color.stroke, ax.tickcolor) .style('stroke-width', Drawing.crispRound(gd, ax.tickwidth, 1) + 'px') - .attr('d', opts.path); + .attr('d', opts.path) + .style('display', null); // visible + + hideCounterAxisInsideTickLabels(ax, [TICK_PATH]); ticks.attr('transform', opts.transFn); }; @@ -2861,7 +2870,10 @@ axes.drawGrid = function(gd, ax, opts) { grid.attr('transform', opts.transFn) .attr('d', opts.path) .call(Color.stroke, ax.gridcolor || '#ddd') - .style('stroke-width', ax._gw + 'px'); + .style('stroke-width', ax._gw + 'px') + .style('display', null); // visible + + hideCounterAxisInsideTickLabels(ax, [GRID_PATH]); if(typeof opts.path === 'function') grid.attr('d', opts.path); }; @@ -2910,7 +2922,10 @@ axes.drawZeroLine = function(gd, ax, opts) { zl.attr('transform', opts.transFn) .attr('d', opts.path) .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) - .style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px'); + .style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px') + .style('display', null); // visible + + hideCounterAxisInsideTickLabels(ax, [ZERO_PATH]); }; /** @@ -2983,7 +2998,10 @@ axes.drawLabels = function(gd, ax, opts) { // sync label: just position it now. positionLabels(thisLabel, tickAngle); } - }); + }) + .style('display', null); // visible + + hideCounterAxisInsideTickLabels(ax, [TICK_TEXT]); tickLabels.exit().remove(); @@ -2995,7 +3013,7 @@ axes.drawLabels = function(gd, ax, opts) { } function positionLabels(s, angle) { - var isInside = (ax.ticklabelposition || '').indexOf('inside') !== -1; + var isInside = insideTicklabelposition(ax); s.each(function(d) { var thisLabel = d3.select(this); @@ -3025,8 +3043,7 @@ axes.drawLabels = function(gd, ax, opts) { }); if(isInside) { - // ensure visible - thisText.style({ opacity: 100 }); + thisText.style('opacity', 0); // visible if(ax._hideOutOfRangeInsideTickLabels) { ax._hideOutOfRangeInsideTickLabels(); @@ -3040,9 +3057,8 @@ axes.drawLabels = function(gd, ax, opts) { }); } - ax._hideOutOfRangeInsideTickLabels = undefined; - if((ax.ticklabelposition || '').indexOf('inside') !== -1) { - ax._hideOutOfRangeInsideTickLabels = function() { + ax._hideOutOfRangeInsideTickLabels = function() { + if(insideTicklabelposition(ax)) { var rl = Lib.simpleMap(ax.range, ax.r2l); // hide inside tick labels that go outside axis end points @@ -3052,8 +3068,12 @@ axes.drawLabels = function(gd, ax, opts) { var min = Math.min(p0, p1) + ax._offset; var max = Math.max(p0, p1) + ax._offset; + var side = ax.side; var isX = ax._id.charAt(0) === 'x'; + var visibleLabelMin = Infinity; + var visibleLabelMax = -Infinity; + tickLabels.each(function(d) { var thisLabel = d3.select(this); var mathjaxGroup = thisLabel.select('.text-math-group'); @@ -3068,11 +3088,69 @@ axes.drawLabels = function(gd, ax, opts) { if(bb.bottom > max) hide = true; else if(bb.top + (ax.tickangle ? 0 : d.fontSize / 4) < min) hide = true; } - if(hide) thisLabel.select('text').style({ opacity: 0 }); + + var t = thisLabel.select('text'); + if(hide) { + t.style('opacity', 0); // hidden + } else { + t.style('opacity', 1); // visible + + if(side === 'bottom' || side === 'right') { + visibleLabelMin = Math.min(visibleLabelMin, isX ? bb.top : bb.left); + } else { + visibleLabelMin = -Infinity; + } + + if(side === 'top' || side === 'left') { + visibleLabelMax = Math.max(visibleLabelMax, isX ? bb.bottom : bb.right); + } else { + visibleLabelMax = Infinity; + } + } } // TODO: hide mathjax? }); - }; - } + + if(ax._anchorAxis) { + ax._anchorAxis._visibleLabelMin = visibleLabelMin; + ax._anchorAxis._visibleLabelMax = visibleLabelMax; + } + } + }; + + ax._hideCounterAxisInsideTickLabels = function(partialOpts) { + if(insideTicklabelposition(ax._anchorAxis || {})) { + (partialOpts || [ + ZERO_PATH, + GRID_PATH, + TICK_PATH, + TICK_TEXT + ]).forEach(function(e) { + var isTickText = e.K === 'tick' && e.L === 'text'; + if(isTickText && ax.ticklabelmode === 'period') return; + + var sel; + if(e.K === ZERO_PATH.K) sel = opts.plotinfo.zerolinelayer.selectAll('.' + ax._id + 'zl'); + else if(e.K === GRID_PATH.K) sel = opts.plotinfo.gridlayer.selectAll('.' + ax._id); + else sel = opts.plotinfo[ax._id.charAt(0) + 'axislayer']; + + sel.each(function() { + var w = d3.select(this); + if(e.L) w = w.selectAll(e.L); + + w.each(function(d) { + var q = ax.l2p(d.x) + ax._offset; + + var t = d3.select(this); + if(q < ax._visibleLabelMax && q > ax._visibleLabelMin) { + t.style('display', 'none'); // hidden + } else if(e.K === 'tick') { + t.style('display', null); // visible + } + }); + }); + }); + } + }; // make sure all labels are correctly positioned at their base angle // the positionLabels call above is only for newly drawn labels. @@ -3201,7 +3279,7 @@ axes.drawLabels = function(gd, ax, opts) { var anchorAx = ax._anchorAxis; if( anchorAx && anchorAx.autorange && - (ax.ticklabelposition || '').indexOf('inside') !== -1 && + insideTicklabelposition(ax) && !isLinked(fullLayout, ax._id) ) { if(!fullLayout._insideTickLabelsAutorange) { @@ -3350,7 +3428,7 @@ function drawTitle(gd, ax) { if(ax.title.hasOwnProperty('standoff')) { titleStandoff = ax._depth + ax.title.standoff + approxTitleDepth(ax); } else { - var isInside = (ax.ticklabelposition || '').indexOf('inside') !== -1; + var isInside = insideTicklabelposition(ax); if(ax.type === 'multicategory') { titleStandoff = ax._depth; @@ -3708,3 +3786,15 @@ function moveOutsideBreak(v, ax) { } return v; } + +function insideTicklabelposition(ax) { + return ((ax.ticklabelposition || '').indexOf('inside') !== -1); +} + +function hideCounterAxisInsideTickLabels(ax, opts) { + if(insideTicklabelposition(ax._anchorAxis || {})) { + if(ax._hideCounterAxisInsideTickLabels) { + ax._hideCounterAxisInsideTickLabels(opts); + } + } +} diff --git a/src/plots/plots.js b/src/plots/plots.js index 4e4ae1574b7..f58b0e9345d 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -2076,17 +2076,21 @@ plots.doAutoMargin = function(gd) { } } - hideOutOfRangeInsideTickLabels(gd); + hideInsideTickLabels(gd); }; -function hideOutOfRangeInsideTickLabels(gd) { +function hideInsideTickLabels(gd) { var axList = axisIDs.list(gd, '', true); - for(var i = 0; i < axList.length; i++) { - var ax = axList[i]; - var hideFn = ax._hideOutOfRangeInsideTickLabels; - if(hideFn) hideFn(); - } + [ + '_hideOutOfRangeInsideTickLabels', + '_hideCounterAxisInsideTickLabels' + ].forEach(function(k) { + for(var i = 0; i < axList.length; i++) { + var hideFn = axList[i][k]; + if(hideFn) hideFn(); + } + }); } var marginKeys = ['l', 'r', 't', 'b', 'p', 'w', 'h']; diff --git a/test/image/baselines/axes_chain_scaleanchor_matches2_inside-ticklabels.png b/test/image/baselines/axes_chain_scaleanchor_matches2_inside-ticklabels.png index 2f9ac8cb2ab..bb08b0dd39c 100644 Binary files a/test/image/baselines/axes_chain_scaleanchor_matches2_inside-ticklabels.png and b/test/image/baselines/axes_chain_scaleanchor_matches2_inside-ticklabels.png differ diff --git a/test/image/baselines/ticklabelposition-1.png b/test/image/baselines/ticklabelposition-1.png index 0f1e12500f1..5cf0249768e 100644 Binary files a/test/image/baselines/ticklabelposition-1.png and b/test/image/baselines/ticklabelposition-1.png differ diff --git a/test/image/baselines/ticklabelposition-2.png b/test/image/baselines/ticklabelposition-2.png index 3b1741078e1..d07def0c695 100644 Binary files a/test/image/baselines/ticklabelposition-2.png and b/test/image/baselines/ticklabelposition-2.png differ diff --git a/test/image/baselines/ticklabelposition-3.png b/test/image/baselines/ticklabelposition-3.png index b611877fc94..99eb5252f79 100644 Binary files a/test/image/baselines/ticklabelposition-3.png and b/test/image/baselines/ticklabelposition-3.png differ diff --git a/test/image/baselines/ticklabelposition-4.png b/test/image/baselines/ticklabelposition-4.png index 3ea9821027f..8605b73289b 100644 Binary files a/test/image/baselines/ticklabelposition-4.png and b/test/image/baselines/ticklabelposition-4.png differ diff --git a/test/image/baselines/ticklabelposition-5.png b/test/image/baselines/ticklabelposition-5.png index 63bbb6333b1..8b3a1a978c5 100644 Binary files a/test/image/baselines/ticklabelposition-5.png and b/test/image/baselines/ticklabelposition-5.png differ diff --git a/test/image/baselines/ticklabelposition-6.png b/test/image/baselines/ticklabelposition-6.png index 5c3baa54acb..3d74250f0a3 100644 Binary files a/test/image/baselines/ticklabelposition-6.png and b/test/image/baselines/ticklabelposition-6.png differ diff --git a/test/image/baselines/ticklabelposition-a.png b/test/image/baselines/ticklabelposition-a.png index e1b33ec3ba6..dc17f6fc3c0 100644 Binary files a/test/image/baselines/ticklabelposition-a.png and b/test/image/baselines/ticklabelposition-a.png differ diff --git a/test/image/baselines/ticklabelposition-c.png b/test/image/baselines/ticklabelposition-c.png index 254313adf02..bbbeaf25841 100644 Binary files a/test/image/baselines/ticklabelposition-c.png and b/test/image/baselines/ticklabelposition-c.png differ diff --git a/test/image/baselines/ticklabelposition-d.png b/test/image/baselines/ticklabelposition-d.png index 30765e2817a..47fa839ac64 100644 Binary files a/test/image/baselines/ticklabelposition-d.png and b/test/image/baselines/ticklabelposition-d.png differ