diff --git a/draftlogs/6712_add.md b/draftlogs/6712_add.md new file mode 100644 index 00000000000..ac47acf1823 --- /dev/null +++ b/draftlogs/6712_add.md @@ -0,0 +1 @@ +- Allow to remove a scaleanchor constraint that is set by default [[#6712](https://github.com/plotly/plotly.js/pull/6712)], with thanks to @lvlte for the contribution! diff --git a/src/plots/cartesian/constraints.js b/src/plots/cartesian/constraints.js index 27596ff4eb9..d825cd92e3e 100644 --- a/src/plots/cartesian/constraints.js +++ b/src/plots/cartesian/constraints.js @@ -253,7 +253,7 @@ function handleOneAxDefaults(axIn, axOut, opts) { scaleanchor = Lib.coerce(axIn, axOut, { scaleanchor: { valType: 'enumerated', - values: linkableAxes + values: linkableAxes.concat([false]) } }, 'scaleanchor', scaleanchorDflt); } diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 94cc77d9d9f..b3854603116 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -330,12 +330,13 @@ module.exports = { ].join(' ') }, // scaleanchor: not used directly, just put here for reference - // values are any opposite-letter axis id + // values are any opposite-letter axis id, or `false`. scaleanchor: { valType: 'enumerated', values: [ constants.idRegex.x.toString(), - constants.idRegex.y.toString() + constants.idRegex.y.toString(), + false ], editType: 'plot', description: [ @@ -353,7 +354,12 @@ module.exports = { 'and the last constraint encountered will be ignored to avoid possible', 'inconsistent constraints via `scaleratio`.', 'Note that setting axes simultaneously in both a `scaleanchor` and a `matches` constraint', - 'is currently forbidden.' + 'is currently forbidden.', + 'Setting `false` allows to remove a default constraint (occasionally,', + 'you may need to prevent a default `scaleanchor` constraint from', + 'being applied, eg. when having an image trace `yaxis: {scaleanchor: "x"}`', + 'is set automatically in order for pixels to be rendered as squares,', + 'setting `yaxis: {scaleanchor: false}` allows to remove the constraint).' ].join(' ') }, scaleratio: { diff --git a/test/jasmine/tests/image_test.js b/test/jasmine/tests/image_test.js index a5fe6fd4a77..81fa1d28105 100644 --- a/test/jasmine/tests/image_test.js +++ b/test/jasmine/tests/image_test.js @@ -209,6 +209,14 @@ describe('image smart layout defaults', function() { expect(gd._fullLayout.yaxis.scaleanchor).toBe('x'); }); + it('should NOT set scaleanchor if asked not to', function() { + gd = {}; + gd.data = [{type: 'image', z: [[[255, 0, 0]]]}]; + gd.layout = {yaxis: {scaleanchor: false}}; + supplyAllDefaults(gd); + expect(gd._fullLayout.yaxis.scaleanchor).toBe(false); + }); + it('should NOT reset scaleanchor if it\'s already defined', function() { gd.data = [{type: 'image', z: [[[255, 0, 0]]]}, {y: [5, 3, 2], xaxis: 'x3'}]; gd.layout = {yaxis: {scaleanchor: 'x3'}}; diff --git a/test/plot-schema.json b/test/plot-schema.json index 8e8dcb0356c..6a1f962255c 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -11157,12 +11157,13 @@ }, "role": "object", "scaleanchor": { - "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`. Note that setting axes simultaneously in both a `scaleanchor` and a `matches` constraint is currently forbidden.", + "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`. Note that setting axes simultaneously in both a `scaleanchor` and a `matches` constraint is currently forbidden. Setting `false` allows to remove a default constraint (occasionally, you may need to prevent a default `scaleanchor` constraint from being applied, eg. when having an image trace `yaxis: {scaleanchor: \"x\"}` is set automatically in order for pixels to be rendered as squares, setting `yaxis: {scaleanchor: false}` allows to remove the constraint).", "editType": "plot", "valType": "enumerated", "values": [ "/^x([2-9]|[1-9][0-9]+)?( domain)?$/", - "/^y([2-9]|[1-9][0-9]+)?( domain)?$/" + "/^y([2-9]|[1-9][0-9]+)?( domain)?$/", + false ] }, "scaleratio": { @@ -12167,12 +12168,13 @@ }, "role": "object", "scaleanchor": { - "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`. Note that setting axes simultaneously in both a `scaleanchor` and a `matches` constraint is currently forbidden.", + "description": "If set to another axis id (e.g. `x2`, `y`), the range of this axis changes together with the range of the corresponding axis such that the scale of pixels per unit is in a constant ratio. Both axes are still zoomable, but when you zoom one, the other will zoom the same amount, keeping a fixed midpoint. `constrain` and `constraintoward` determine how we enforce the constraint. You can chain these, ie `yaxis: {scaleanchor: *x*}, xaxis2: {scaleanchor: *y*}` but you can only link axes of the same `type`. The linked axis can have the opposite letter (to constrain the aspect ratio) or the same letter (to match scales across subplots). Loops (`yaxis: {scaleanchor: *x*}, xaxis: {scaleanchor: *y*}` or longer) are redundant and the last constraint encountered will be ignored to avoid possible inconsistent constraints via `scaleratio`. Note that setting axes simultaneously in both a `scaleanchor` and a `matches` constraint is currently forbidden. Setting `false` allows to remove a default constraint (occasionally, you may need to prevent a default `scaleanchor` constraint from being applied, eg. when having an image trace `yaxis: {scaleanchor: \"x\"}` is set automatically in order for pixels to be rendered as squares, setting `yaxis: {scaleanchor: false}` allows to remove the constraint).", "editType": "plot", "valType": "enumerated", "values": [ "/^x([2-9]|[1-9][0-9]+)?( domain)?$/", - "/^y([2-9]|[1-9][0-9]+)?( domain)?$/" + "/^y([2-9]|[1-9][0-9]+)?( domain)?$/", + false ] }, "scaleratio": {