diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index a83337f780e..423a856809c 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -571,12 +571,14 @@ axes.calcTicks = function calcTicks(ax) { if((ax._tmin < startTick) !== axrev) return []; // return the full set of tick vals - var vals = []; + var tickVals = []; if(ax.type === 'category' || ax.type === 'multicategory') { endTick = (axrev) ? Math.max(-0.5, endTick) : Math.min(ax._categories.length - 0.5, endTick); } + var isDLog = (ax.type === 'log') && !(isNumeric(ax.dtick) || ax.dtick.charAt(0) === 'L'); + var xPrevious = null; var maxTicks = Math.max(1000, ax._length || 0); for(var x = ax._tmin; @@ -584,21 +586,29 @@ axes.calcTicks = function calcTicks(ax) { x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) { // prevent infinite loops - no more than one tick per pixel, // and make sure each value is different from the previous - if(vals.length > maxTicks || x === xPrevious) break; + if(tickVals.length > maxTicks || x === xPrevious) break; xPrevious = x; - vals.push(x); + var minor = false; + if(isDLog && (x !== (x | 0))) { + minor = true; + } + + tickVals.push({ + minor: minor, + value: x + }); } // If same angle over a full circle, the last tick vals is a duplicate. // TODO must do something similar for angular date axes. if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) { - vals.pop(); + tickVals.pop(); } // save the last tick as well as first, so we can // show the exponent only on the last one - ax._tmax = vals[vals.length - 1]; + ax._tmax = (tickVals[tickVals.length - 1] || {}).value; // for showing the rest of a date when the main tick label is only the // latter part: ax._prevDateHead holds what we showed most recently. @@ -607,8 +617,15 @@ axes.calcTicks = function calcTicks(ax) { ax._prevDateHead = ''; ax._inCalcTicks = true; - var ticksOut = new Array(vals.length); - for(var i = 0; i < vals.length; i++) ticksOut[i] = axes.tickText(ax, vals[i]); + var ticksOut = new Array(tickVals.length); + for(var i = 0; i < tickVals.length; i++) { + ticksOut[i] = axes.tickText( + ax, + tickVals[i].value, + false, // hover + tickVals[i].minor // noSuffixPrefix + ); + } ax._inCalcTicks = false; @@ -937,7 +954,7 @@ axes.tickFirst = function(ax) { // ax is the axis layout, x is the tick value // hover is a (truthy) flag for whether to show numbers with a bit // more precision for hovertext -axes.tickText = function(ax, x, hover) { +axes.tickText = function(ax, x, hover, noSuffixPrefix) { var out = tickTextObj(ax, x); var arrayMode = ax.tickmode === 'array'; var extraPrecision = hover || arrayMode; @@ -983,8 +1000,10 @@ axes.tickText = function(ax, x, hover) { else formatLinear(ax, out, hover, extraPrecision, hideexp); // add prefix and suffix - if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; - if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; + if(!noSuffixPrefix) { + if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; + if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; + } // Setup ticks and grid lines boundaries // at 1/2 a 'category' to the left/bottom diff --git a/test/image/baselines/log-axis_no-minor_suffix-prefix.png b/test/image/baselines/log-axis_no-minor_suffix-prefix.png new file mode 100644 index 00000000000..0c3dd72e759 Binary files /dev/null and b/test/image/baselines/log-axis_no-minor_suffix-prefix.png differ diff --git a/test/image/mocks/log-axis_no-minor_suffix-prefix.json b/test/image/mocks/log-axis_no-minor_suffix-prefix.json new file mode 100644 index 00000000000..c5eeabf8321 --- /dev/null +++ b/test/image/mocks/log-axis_no-minor_suffix-prefix.json @@ -0,0 +1,121 @@ +{ + "data": [ + { + "name": "L10000000", + "y": [ + 1e8, + 1e6, + 1e7 + ], + "type": "scatter" + }, + { + "name": "dtick=0.5 | tick0=1", + "xaxis": "x2", + "yaxis": "y2", + "y": [ + 1e8, + 1e6, + 1e7 + ], + "type": "scatter" + }, + { + "name": "D1", + "xaxis": "x3", + "yaxis": "y3", + "y": [ + 1e8, + 1e6, + 1e7 + ], + "type": "scatter" + }, + { + "name": "default", + "xaxis": "x4", + "yaxis": "y4", + "y": [ + 1e8, + 1e6, + 1e7 + ], + "type": "scatter" + } + ], + "layout": { + "width": 800, + "height": 800, + "xaxis": { + "domain": [ + 0, + 0.45 + ] + }, + "xaxis2": { + "anchor": "y2", + "domain": [ + 0.6, + 1 + ] + }, + "xaxis3": { + "anchor": "y3", + "domain": [ + 0, + 0.45 + ] + }, + "xaxis4": { + "anchor": "y4", + "domain": [ + 0.6, + 1 + ] + }, + "yaxis": { + "tick0": 1, + "dtick": "L10000000", + "type": "log", + "tickprefix": "$", + "ticksuffix": "Hz", + "domain": [ + 0, + 0.45 + ] + }, + "yaxis2": { + "tick0": 1, + "dtick": 0.5, + "type": "log", + "tickprefix": "$", + "ticksuffix": "Hz", + "anchor": "x2", + "domain": [ + 0, + 0.45 + ] + }, + "yaxis3": { + "dtick": "D1", + "type": "log", + "tickprefix": "$", + "ticksuffix": "Hz", + "anchor": "x3", + "domain": [ + 0.6, + 1 + ] + }, + "yaxis4": { + "type": "log", + "tickprefix": "$", + "ticksuffix": "Hz", + "anchor": "x4", + "domain": [ + 0.6, + 1 + ] + } + } +}