diff --git a/src/plots/polar/polar.js b/src/plots/polar/polar.js index df9d53a9589..23a1faebca6 100644 --- a/src/plots/polar/polar.js +++ b/src/plots/polar/polar.js @@ -416,14 +416,15 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) { _counteraxis: true, // don't use automargins routine for labels - automargin: false + automargin: false, + + // don't pass through autorange logic + autorange: false }); // Set the angular range in degrees to make auto-tick computation cleaner, // changing rotation/direction should not affect the angular tick labels. if(ax.type === 'linear') { - ax.autorange = false; - if(isFullCircle(sector)) { ax.range = sector.slice(); } else { @@ -435,11 +436,18 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) { ax.tick0 = rad2deg(ax.tick0); ax.dtick = rad2deg(ax.dtick); } + } // Use tickval filter for category axes instead of tweaking // the range w.r.t sector, so that sectors that cross 360 can // show all their ticks. else if(ax.type === 'category') { + var period = angularLayout.period ? + Math.max(angularLayout.period, angularLayout._categories.length) : + angularLayout._categories.length; + + ax.range = [0, period]; + ax._tickFilter = function(d) { return _this.isPtWithinSector({ r: _this.radialAxis.range[1], @@ -449,7 +457,6 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) { } setScale(ax, angularLayout, fullLayout); - doAutoRange(ax); // wrapper around c2rad from setConvertAngular // note that linear ranges are always set in degrees for Axes.doTicks diff --git a/src/traces/scatterpolar/calc.js b/src/traces/scatterpolar/calc.js index 4c600509cff..7d9662324d0 100644 --- a/src/traces/scatterpolar/calc.js +++ b/src/traces/scatterpolar/calc.js @@ -50,12 +50,6 @@ module.exports = function calc(gd, trace) { var ppad = calcMarkerSize(trace, len); Axes.expand(radialAxis, rArray, {ppad: ppad}); - if(angularAxis.type !== 'linear') { - angularAxis.autorange = true; - Axes.expand(angularAxis, thetaArray); - delete angularAxis.autorange; - } - calcColorscale(trace); arraysToCalcdata(cd, trace); calcSelection(cd, trace); diff --git a/test/jasmine/tests/polar_test.js b/test/jasmine/tests/polar_test.js index 8583cb00225..ac5304d72a7 100644 --- a/test/jasmine/tests/polar_test.js +++ b/test/jasmine/tests/polar_test.js @@ -543,6 +543,65 @@ describe('Test relayout on polar subplots:', function() { .catch(fail) .then(done); }); + + it('should update axis ranges when extending traces', function(done) { + var gd = createGraphDiv(); + + function _assert(msg, exp) { + expect(gd._fullLayout.polar.radialaxis.autorange).toBe(true); + + expect(gd.layout.polar.radialaxis.range) + .toBeCloseToArray(exp.rRange, 2, 'radial range in user layout - ' + msg); + expect(gd._fullLayout.polar.radialaxis.range) + .toBeCloseToArray(exp.rRange, 2, 'radial range in full layout - ' + msg); + + expect(gd._fullLayout.polar._subplot.angularAxis.range) + .toBeCloseToArray([0, exp.period], 2, 'range in mocked angular axis - ' + msg); + + expect(d3.selectAll('path.angulartick').size()) + .toBe(exp.nTicks, '# of visible angular ticks - ' + msg); + + expect([gd.calcdata[0][5].x, gd.calcdata[0][5].y]) + .toBeCloseToArray(exp.sampleXY, -1, 'sample (x,y) px coords in calcdata - ' + msg); + } + + Plotly.plot(gd, [{ + type: 'scatterpolar', + r: [39, 28, 8, 7, 28, 39, 40, 30, 30, 30, 30], + theta: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'A'] + }]) + .then(function() { + _assert('base', { + rRange: [0, 41.14], + period: 10, + nTicks: 10, + sampleXY: [-39, 0] + }); + return Plotly.extendTraces(gd, { + r: [[-10, -5]], + theta: [['y', 'z']] + }, [0]); + }) + .then(function() { + _assert('after extending trace', { + rRange: [-11.47, 41.47], + period: 12, + nTicks: 12, + sampleXY: [-43, 25] + }); + return Plotly.relayout(gd, 'polar.angularaxis.period', 15); + }) + .then(function() { + _assert('after angularaxis.period relayout', { + rRange: [-11.47, 41.47], + period: 15, + nTicks: 12, + sampleXY: [-25, 43] + }); + }) + .catch(fail) + .then(done); + }); }); describe('Test polar interactions:', function() {