Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ef3ca48

Browse filesBrowse files
committed
allow constraints with same axis letter
1 parent dee136d commit ef3ca48
Copy full SHA for ef3ca48

File tree

Expand file treeCollapse file tree

6 files changed

+87
-68
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+87
-68
lines changed
Open diff view settings
Collapse file

‎src/plots/cartesian/constraint_defaults.js‎

Copy file name to clipboardExpand all lines: src/plots/cartesian/constraint_defaults.js
+9-7Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ var Lib = require('../../lib');
1313
var id2name = require('./axis_ids').id2name;
1414

1515

16-
module.exports = function handleConstraintDefaults(containerIn, containerOut, coerce, counterAxes, layoutOut) {
16+
module.exports = function handleConstraintDefaults(containerIn, containerOut, coerce, allAxisIds, layoutOut) {
1717
var constraintGroups = layoutOut._axisConstraintGroups;
1818

1919
if(containerOut.fixedrange || !containerIn.scaleanchor) return;
2020

21-
var constraintOpts = getConstraintOpts(constraintGroups, containerOut._id, counterAxes, layoutOut);
21+
var constraintOpts = getConstraintOpts(constraintGroups, containerOut._id, allAxisIds, layoutOut);
2222

2323
var scaleanchor = Lib.coerce(containerIn, containerOut, {
2424
scaleanchor: {
@@ -39,26 +39,28 @@ module.exports = function handleConstraintDefaults(containerIn, containerOut, co
3939
updateConstraintGroups(constraintGroups, constraintOpts.thisGroup,
4040
containerOut._id, scaleanchor, scaleratio);
4141
}
42-
else if(counterAxes.indexOf(containerIn.scaleanchor) !== -1) {
42+
else if(allAxisIds.indexOf(containerIn.scaleanchor) !== -1) {
4343
Lib.warn('ignored ' + containerOut._name + '.scaleanchor: "' +
4444
containerIn.scaleanchor + '" to avoid either an infinite loop ' +
4545
'and possibly inconsistent scaleratios, or because the target' +
4646
'axis has fixed range.');
4747
}
4848
};
4949

50-
function getConstraintOpts(constraintGroups, thisID, counterAxes, layoutOut) {
50+
function getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut) {
5151
// If this axis is already part of a constraint group, we can't
5252
// scaleanchor any other axis in that group, or we'd make a loop.
53-
// Filter counterAxes to enforce this, also matching axis types.
53+
// Filter allAxisIds to enforce this, also matching axis types.
5454

5555
var thisType = layoutOut[id2name(thisID)].type;
5656

5757
var i, j, idj, axj;
5858

5959
var linkableAxes = [];
60-
for(j = 0; j < counterAxes.length; j++) {
61-
idj = counterAxes[j];
60+
for(j = 0; j < allAxisIds.length; j++) {
61+
idj = allAxisIds[j];
62+
if(idj === thisID) continue;
63+
6264
axj = layoutOut[id2name(idj)];
6365
if(axj.type === thisType && !axj.fixedrange) linkableAxes.push(idj);
6466
}
Collapse file

‎src/plots/cartesian/dragbox.js‎

Copy file name to clipboardExpand all lines: src/plots/cartesian/dragbox.js
+60-52Lines changed: 60 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -659,80 +659,88 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
659659
// affected by this drag, and update them. look for all plots
660660
// sharing an affected axis (including the one being dragged)
661661
function updateSubplots(viewBox) {
662-
var j;
663-
var plotinfos = fullLayout._plots,
664-
subplots = Object.keys(plotinfos);
662+
var plotinfos = fullLayout._plots;
663+
var subplots = Object.keys(plotinfos);
664+
var xScaleFactor = viewBox[2] / xa[0]._length;
665+
var yScaleFactor = viewBox[3] / ya[0]._length;
666+
var editX = ew || isSubplotConstrained;
667+
var editY = ns || isSubplotConstrained;
668+
669+
var i, xScaleFactor2, yScaleFactor2, clipDx, clipDy;
670+
671+
// Find the appropriate scaling for this axis, if it's linked to the
672+
// dragged axes by constraints. 0 is special, it means this axis shouldn't
673+
// ever be scaled (will be converted to 1 if the other axis is scaled)
674+
function getLinkedScaleFactor(ax) {
675+
if(ax.fixedrange) return 0;
676+
677+
if(editX && xaLinked.indexOf(ax) !== -1) {
678+
return xScaleFactor;
679+
}
680+
if(editY && (isSubplotConstrained ? xaLinked : yaLinked).indexOf(ax) !== -1) {
681+
return yScaleFactor;
682+
}
683+
return 0;
684+
}
685+
686+
function scaleAndGetShift(ax, scaleFactor) {
687+
if(scaleFactor) {
688+
ax.range = ax._r.slice();
689+
scaleZoom(ax, scaleFactor);
690+
return ax._length * (1 - scaleFactor) / 2;
691+
}
692+
return 0;
693+
}
665694

666-
for(var i = 0; i < subplots.length; i++) {
695+
for(i = 0; i < subplots.length; i++) {
667696

668697
var subplot = plotinfos[subplots[i]],
669698
xa2 = subplot.xaxis,
670699
ya2 = subplot.yaxis,
671-
editX = (viewBox[0] !== 0 || viewBox[2] !== pw) && !xa2.fixedrange,
672-
editY = (viewBox[1] !== 0 || viewBox[3] !== ph) && !ya2.fixedrange;
673-
674-
if(editX) {
675-
// TODO: now that we're doing recomputeAxisLists can this be turned into
676-
// just xa.indexOf(xa2) !== -1?
677-
var isInX = false;
678-
for(j = 0; j < xa.length; j++) {
679-
if(xa[j]._id === xa2._id) {
680-
isInX = true;
681-
break;
682-
}
683-
}
684-
editX = editX && isInX;
685-
}
700+
editX2 = editX && !xa2.fixedrange && (xa.indexOf(xa2) !== -1),
701+
editY2 = editY && !ya2.fixedrange && (ya.indexOf(ya2) !== -1);
686702

687-
if(editY) {
688-
var isInY = false;
689-
for(j = 0; j < ya.length; j++) {
690-
if(ya[j]._id === ya2._id) {
691-
isInY = true;
692-
break;
693-
}
694-
}
695-
editY = editY && isInY;
703+
if(editX2) {
704+
xScaleFactor2 = xScaleFactor;
705+
clipDx = viewBox[0];
706+
}
707+
else {
708+
xScaleFactor2 = getLinkedScaleFactor(xa2);
709+
clipDx = scaleAndGetShift(xa2, xScaleFactor2);
696710
}
697711

698-
var xScaleFactor = editX ? viewBox[2] / xa2._length : 1,
699-
yScaleFactor = editY ? viewBox[3] / ya2._length : 1;
700-
701-
var clipDx = editX ? viewBox[0] : 0,
702-
clipDy = editY ? viewBox[1] : 0;
703-
704-
// modify these if needed for linked axes
705-
if(editX && !editY && xaLinked.indexOf(ya2) !== -1) {
706-
yScaleFactor = xScaleFactor;
707-
clipDy = ya2._length * (1 - yScaleFactor) / 2;
708-
709-
// update range for the linked axis.
710-
ya2.range = ya2._r.slice();
711-
scaleZoom(ya2, yScaleFactor);
712+
if(editY2) {
713+
yScaleFactor2 = yScaleFactor;
714+
clipDy = viewBox[1];
712715
}
713-
if(editY && !editX && (isSubplotConstrained ? xaLinked : yaLinked).indexOf(xa2) !== -1) {
714-
xScaleFactor = yScaleFactor;
715-
clipDx = xa2._length * (1 - xScaleFactor) / 2;
716-
xa2.range = xa2._r.slice();
717-
scaleZoom(xa2, xScaleFactor);
716+
else {
717+
yScaleFactor2 = getLinkedScaleFactor(ya2);
718+
clipDy = scaleAndGetShift(ya2, yScaleFactor2);
718719
}
719720

720-
var plotDx = xa2._offset - clipDx / xScaleFactor,
721-
plotDy = ya2._offset - clipDy / yScaleFactor;
721+
// don't scale at all if neither axis is scalable here
722+
if(!xScaleFactor2 && !yScaleFactor2) continue;
723+
724+
// but if only one is, reset the other axis scaling
725+
if(!xScaleFactor2) xScaleFactor2 = 1;
726+
if(!yScaleFactor2) yScaleFactor2 = 1;
727+
728+
var plotDx = xa2._offset - clipDx / xScaleFactor2,
729+
plotDy = ya2._offset - clipDy / yScaleFactor2;
722730

723731
fullLayout._defs.selectAll('#' + subplot.clipId)
724732
.call(Drawing.setTranslate, clipDx, clipDy)
725-
.call(Drawing.setScale, xScaleFactor, yScaleFactor);
733+
.call(Drawing.setScale, xScaleFactor2, yScaleFactor2);
726734

727735
subplot.plot
728736
.call(Drawing.setTranslate, plotDx, plotDy)
729-
.call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor)
737+
.call(Drawing.setScale, 1 / xScaleFactor2, 1 / yScaleFactor2)
730738

731739
// This is specifically directed at scatter traces, applying an inverse
732740
// scale to individual points to counteract the scale of the trace
733741
// as a whole:
734742
.select('.scatterlayer').selectAll('.points').selectAll('.point')
735-
.call(Drawing.setPointGroupScale, xScaleFactor, yScaleFactor);
743+
.call(Drawing.setPointGroupScale, xScaleFactor2, yScaleFactor2);
736744
}
737745
}
738746

Collapse file

‎src/plots/cartesian/layout_defaults.js‎

Copy file name to clipboardExpand all lines: src/plots/cartesian/layout_defaults.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
231231
// sets of axes linked by `scaleanchor` along with the scaleratios compounded
232232
// together, populated in handleConstraintDefaults
233233
layoutOut._axisConstraintGroups = [];
234+
var allAxisIds = counterAxes.x.concat(counterAxes.y);
234235

235236
for(i = 0; i < axesList.length; i++) {
236237
axName = axesList[i];
@@ -239,6 +240,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
239240
axLayoutIn = layoutIn[axName];
240241
axLayoutOut = layoutOut[axName];
241242

242-
handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, counterAxes[axLetter], layoutOut);
243+
handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, allAxisIds, layoutOut);
243244
}
244245
};
Collapse file
15.2 KB
  • Display the source diff
  • Display the rich diff
Loading
Collapse file
+9-4Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
{
22
"data":[
33
{"x": [0,1,1,0,0,1,1,2,2,3,3,2,2,3], "y": [0,0,1,1,3,3,2,2,3,3,1,1,0,0]},
4-
{"x": [0,1,2,3], "y": [1,2,4,8], "yaxis":"y2"}
4+
{"x": [0,1,2,3], "y": [1,2,4,8], "yaxis":"y2"},
5+
{"x": [1,10,100,10,1], "y": [0,1,2,3,4], "xaxis":"x2", "yaxis":"y3"},
6+
{"x": [1,100,30,80,1], "y": [1,1.5,2,2.5,3], "xaxis":"x2", "yaxis":"y4"}
57
],
68
"layout":{
7-
"width": 600,
8-
"height":600,
9+
"width": 800,
10+
"height":500,
911
"title": "fixed-ratio axes",
10-
"xaxis": {"nticks": 10, "title": "shared X axis"},
12+
"xaxis": {"nticks": 10, "domain": [0, 0.45], "title": "shared X axis"},
1113
"yaxis": {"scaleanchor": "x", "domain": [0, 0.45], "title": "1:1"},
1214
"yaxis2": {"scaleanchor": "x", "scaleratio": 0.2, "domain": [0.55,1], "title": "1:5"},
15+
"xaxis2": {"type": "log", "domain": [0.55, 1], "title": "unconstrained log X"},
16+
"yaxis3": {"domain": [0, 0.45], "anchor": "x2", "title": "Scale matches ->"},
17+
"yaxis4": {"scaleanchor": "y3", "domain": [0.55, 1], "anchor": "x2", "title": "Scale matches <-"},
1318
"showlegend": false
1419
}
1520
}
Collapse file

‎test/jasmine/tests/axes_test.js‎

Copy file name to clipboardExpand all lines: test/jasmine/tests/axes_test.js
+7-4Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,18 +475,21 @@ describe('Test axes', function() {
475475

476476
layoutIn = {
477477
xaxis: {scaleanchor: 'y', scaleratio: 2},
478-
yaxis: {scaleanchor: 'x', scaleratio: 3},
478+
yaxis: {scaleanchor: 'x', scaleratio: 3}, // dropped loop
479479

480480
xaxis2: {scaleanchor: 'y2', scaleratio: 5},
481481
yaxis2: {scaleanchor: 'x3', scaleratio: 7},
482482
xaxis3: {scaleanchor: 'y3', scaleratio: 9},
483-
yaxis3: {scaleanchor: 'x2', scaleratio: 11}
483+
yaxis3: {scaleanchor: 'x2', scaleratio: 11}, // dropped loop
484+
485+
xaxis4: {scaleanchor: 'x', scaleratio: 13}, // x<->x is OK now
486+
yaxis4: {scaleanchor: 'y', scaleratio: 17}, // y<->y is OK now
484487
};
485488

486489
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
487490

488491
expect(layoutOut._axisConstraintGroups).toEqual([
489-
{x: 2, y: 1},
492+
{x: 2, y: 1, x4: 2 * 13, y4: 17},
490493
{x2: 5 * 7 * 9, y2: 7 * 9, y3: 1, x3: 9}
491494
]);
492495

@@ -507,7 +510,7 @@ describe('Test axes', function() {
507510
});
508511

509512
layoutIn = {
510-
xaxis: {scaleanchor: 'x2', scaleratio: 2}, // must be opposite letter
513+
xaxis: {scaleanchor: 'x', scaleratio: 2}, // can't link to itself
511514
yaxis: {scaleanchor: 'x4', scaleratio: 3}, // doesn't exist
512515
xaxis2: {scaleanchor: 'yaxis', scaleratio: 5} // must be an id, not a name
513516
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.