diff --git a/src/plots/cartesian/constraints.js b/src/plots/cartesian/constraints.js index d3c0c138152..925aba2c05d 100644 --- a/src/plots/cartesian/constraints.js +++ b/src/plots/cartesian/constraints.js @@ -57,10 +57,7 @@ exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, o // 'matches' wins over 'scaleanchor' (for now) var scaleanchor, scaleOpts; - if(!matches && - !(containerOut.fixedrange && constrain !== 'domain') && - (containerIn.scaleanchor || scaleanchorDflt) - ) { + if(containerIn.scaleanchor || scaleanchorDflt) { scaleOpts = getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut, constrain); scaleanchor = Lib.coerce(containerIn, containerOut, { scaleanchor: { @@ -90,11 +87,6 @@ exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, o if(!scaleratio) scaleratio = containerOut.scaleratio = 1; updateConstraintGroups(constraintGroups, scaleOpts.thisGroup, thisID, scaleanchor, scaleratio); - } else if(allAxisIds.indexOf(containerIn.scaleanchor) !== -1) { - Lib.warn('ignored ' + containerOut._name + '.scaleanchor: "' + - containerIn.scaleanchor + '" to avoid either an infinite loop ' + - 'and possibly inconsistent scaleratios, or because the target ' + - 'axis has fixed range or this axis declares a *matches* constraint.'); } }; diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index 3e411ae0574..5a5f0d9bffa 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -377,7 +377,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { // sets of axes linked by `scaleanchor` along with the scaleratios compounded // together, populated in handleConstraintDefaults - var constraintGroups = layoutOut._axisConstraintGroups = []; + layoutOut._axisConstraintGroups = []; // similar to _axisConstraintGroups, but for matching axes var matchGroups = layoutOut._axisMatchGroups = []; // make sure to include 'missing' axes here @@ -444,26 +444,5 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { } axLayoutOut._matchGroup = group; } - - // remove matching axis from scaleanchor constraint groups (for now) - if(constraintGroups.length) { - for(axId in group) { - for(j = 0; j < constraintGroups.length; j++) { - var group2 = constraintGroups[j]; - for(var axId2 in group2) { - if(axId === axId2) { - Lib.warn('Axis ' + axId2 + ' is set with both ' + - 'a *scaleanchor* and *matches* constraint; ' + - 'ignoring the scale constraint.'); - - delete group2[axId2]; - if(Object.keys(group2).length < 2) { - constraintGroups.splice(j, 1); - } - } - } - } - } - } } }; diff --git a/test/image/baselines/match-and-scale.png b/test/image/baselines/match-and-scale.png new file mode 100644 index 00000000000..653e22ca380 Binary files /dev/null and b/test/image/baselines/match-and-scale.png differ diff --git a/test/image/mocks/match-and-scale.json b/test/image/mocks/match-and-scale.json new file mode 100644 index 00000000000..ddd2ac29d14 --- /dev/null +++ b/test/image/mocks/match-and-scale.json @@ -0,0 +1,49 @@ +{ + "data":[ + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]]}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "xaxis": "x2"}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "xaxis": "x3"}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "yaxis": "y2"}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "yaxis": "y3"}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "yaxis": "y3", "xaxis": "x3"}, + {"type": "image", "z": [[[0, 0, 255], [255, 0, 0]], [[255, 0, 0], [0, 0, 255]]], "yaxis": "y2", "xaxis": "x2"} + ], + "layout":{ + "width": 600, + "height": 600, + "showlegend": false, + "xaxis": { + "scaleanchor": "y", + "constrain": "domain", + "domain": [0, 0.3] + }, + "xaxis2": { + "scaleanchor": "y", + "matches": "x", + "scaleratio": 2, + "domain": [0.35, 0.65] + }, + "xaxis3": { + "scaleanchor": "y", + "matches": "x", + "scaleratio": 1, + "domain": [0.7, 1] + }, + "yaxis": { + "constrain": "domain", + "domain": [0, 0.3] + }, + "yaxis2": { + "matches": "y", + "scaleanchor": "x", + "scaleratio": 2, + "domain": [0.35, 0.65] + }, + "yaxis3": { + "matches": "y", + "scaleanchor": "x", + "scaleratio": 1, + "domain": [0.7, 1] + } + } +} diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 7a135ba11c0..2cd278a42f4 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -591,69 +591,6 @@ describe('Test axes', function() { ]); }); - var warnTxt = ' to avoid either an infinite loop and possibly ' + - 'inconsistent scaleratios, or because the target axis has ' + - 'fixed range or this axis declares a *matches* constraint.'; - - it('breaks scaleanchor loops and drops conflicting ratios', function() { - var warnings = []; - spyOn(Lib, 'warn').and.callFake(function(msg) { - warnings.push(msg); - }); - - layoutIn = { - xaxis: {scaleanchor: 'y', scaleratio: 2}, - yaxis: {scaleanchor: 'x', scaleratio: 3}, // dropped loop - - xaxis2: {scaleanchor: 'y2', scaleratio: 5}, - yaxis2: {scaleanchor: 'x3', scaleratio: 7}, - xaxis3: {scaleanchor: 'y3', scaleratio: 9}, - yaxis3: {scaleanchor: 'x2', scaleratio: 11}, // dropped loop - - xaxis4: {scaleanchor: 'x', scaleratio: 13}, // x<->x is OK now - yaxis4: {scaleanchor: 'y', scaleratio: 17}, // y<->y is OK now - }; - layoutOut._subplots.cartesian.push('x2y2', 'x3y3', 'x4y4'); - layoutOut._subplots.yaxis.push('x2', 'x3', 'x4', 'y2', 'y3', 'y4'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut._axisConstraintGroups).toEqual([ - {x: 2, y: 1, x4: 2 * 13, y4: 17}, - {x2: 5 * 7 * 9, y2: 7 * 9, y3: 1, x3: 9} - ]); - - expect(warnings).toEqual([ - 'ignored yaxis.scaleanchor: "x"' + warnTxt, - 'ignored yaxis3.scaleanchor: "x2"' + warnTxt - ]); - }); - - it('silently drops invalid scaleanchor values', function() { - var warnings = []; - spyOn(Lib, 'warn').and.callFake(function(msg) { - warnings.push(msg); - }); - - layoutIn = { - xaxis: {scaleanchor: 'x', scaleratio: 2}, // can't link to itself - this one isn't ignored... - yaxis: {scaleanchor: 'x4', scaleratio: 3}, // doesn't exist - xaxis2: {scaleanchor: 'yaxis', scaleratio: 5} // must be an id, not a name - }; - layoutOut._subplots.cartesian.push('x2y'); - layoutOut._subplots.yaxis.push('x2'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut._axisConstraintGroups).toEqual([]); - expect(warnings).toEqual(['ignored xaxis.scaleanchor: "x"' + warnTxt]); - - ['xaxis', 'yaxis', 'xaxis2'].forEach(function(axName) { - expect(layoutOut[axName].scaleanchor).toBeUndefined(axName); - expect(layoutOut[axName].scaleratio).toBeUndefined(axName); - }); - }); - it('will not link axes of different types', function() { layoutIn = { xaxis: {type: 'linear'}, @@ -693,93 +630,6 @@ describe('Test axes', function() { }); }); - it('disallow constraining AND matching range', function() { - layoutIn = { - xaxis: {}, - xaxis2: {matches: 'x', scaleanchor: 'x'} - }; - layoutOut._subplots.cartesian.push('x2y'); - layoutOut._subplots.xaxis.push('x2'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut.xaxis2.matches).toBe('x'); - expect(layoutOut.xaxis2.scaleanchor).toBe(undefined); - expect(layoutOut.xaxis2.constrain).toBe(undefined); - - expect(layoutOut._axisConstraintGroups).toEqual([]); - expect(layoutOut._axisMatchGroups).toEqual([{x: 1, x2: 1}]); - }); - - it('remove axes from constraint groups if they are in a match group', function() { - layoutIn = { - // this one is ok - xaxis: {}, - yaxis: {scaleanchor: 'x'}, - // this one too - xaxis2: {}, - yaxis2: {matches: 'x2'}, - // not these ones - xaxis3: {scaleanchor: 'x2'}, - yaxis3: {scaleanchor: 'y2'} - }; - layoutOut._subplots.cartesian.push('x2y2, x3y3'); - layoutOut._subplots.xaxis.push('x2', 'x3'); - layoutOut._subplots.yaxis.push('y2', 'y3'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut._axisMatchGroups.length).toBe(1); - expect(layoutOut._axisMatchGroups).toContain({x2: 1, y2: 1}); - - expect(layoutOut._axisConstraintGroups.length).toBe(1); - expect(layoutOut._axisConstraintGroups).toContain({x: 1, y: 1}); - }); - - it('remove constraint group if they are one or zero items left in it', function() { - layoutIn = { - xaxis: {}, - yaxis: {matches: 'x'}, - xaxis2: {scaleanchor: 'y'} - }; - layoutOut._subplots.cartesian.push('x2y'); - layoutOut._subplots.xaxis.push('x2'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut._axisMatchGroups.length).toBe(1); - expect(layoutOut._axisMatchGroups).toContain({x: 1, y: 1}); - - expect(layoutOut._axisConstraintGroups.length).toBe(0); - }); - - it('drops scaleanchor settings if either the axis or target has fixedrange', function() { - // some of these will create warnings... not too important, so not going to test, - // just want to keep the output clean - // spyOn(Lib, 'warn'); - - layoutIn = { - xaxis: {fixedrange: true, scaleanchor: 'y', scaleratio: 2}, - yaxis: {scaleanchor: 'x2', scaleratio: 3}, // only this one should survive - xaxis2: {}, - yaxis2: {scaleanchor: 'x', scaleratio: 5} - }; - layoutOut._subplots.cartesian.push('x2y2'); - layoutOut._subplots.yaxis.push('x2', 'y2'); - - supplyLayoutDefaults(layoutIn, layoutOut, fullData); - - expect(layoutOut._axisConstraintGroups).toEqual([{x2: 1, y: 3}]); - - expect(layoutOut.yaxis.scaleanchor).toBe('x2'); - expect(layoutOut.yaxis.scaleratio).toBe(3); - - ['xaxis', 'yaxis2', 'xaxis2'].forEach(function(axName) { - expect(layoutOut[axName].scaleanchor).toBeUndefined(); - expect(layoutOut[axName].scaleratio).toBeUndefined(); - }); - }); - it('drops *matches* settings if either the axis or target has fixedrange', function() { layoutIn = { xaxis: {fixedrange: true, matches: 'y'}, diff --git a/test/jasmine/tests/mock_test.js b/test/jasmine/tests/mock_test.js index 86825fc7e0d..d9537411036 100644 --- a/test/jasmine/tests/mock_test.js +++ b/test/jasmine/tests/mock_test.js @@ -726,6 +726,7 @@ var list = [ 'marker_colorscale_template', 'marker_line_width', 'marker_symbols', + 'match-and-scale', 'matching-categories', 'matching-missing-axes', 'mathjax', @@ -1790,6 +1791,7 @@ figs['mapbox_white-bg-style'] = require('@mocks/mapbox_white-bg-style'); figs['marker_colorscale_template'] = require('@mocks/marker_colorscale_template'); figs['marker_line_width'] = require('@mocks/marker_line_width'); figs['marker_symbols'] = require('@mocks/marker_symbols'); +figs['match-and-scale'] = require('@mocks/match-and-scale'); figs['matching-categories'] = require('@mocks/matching-categories'); // figs['matching-missing-axes'] = require('@mocks/matching-missing-axes'); // figs['mathjax'] = require('@mocks/mathjax');