@@ -37,13 +37,16 @@ exports.enforce = function enforceAxisConstraints(gd) {
37
37
var matchScale = Infinity ;
38
38
var normScales = { } ;
39
39
var axes = { } ;
40
+ var hasAnyDomainConstraint = false ;
40
41
41
42
// find the (normalized) scale of each axis in the group
42
43
for ( j = 0 ; j < axisIDs . length ; j ++ ) {
43
44
axisID = axisIDs [ j ] ;
44
45
axes [ axisID ] = ax = fullLayout [ id2name ( axisID ) ] ;
45
46
46
- if ( ! ax . _inputDomain ) ax . _inputDomain = ax . domain . slice ( ) ;
47
+ if ( ax . _inputDomain ) ax . domain = ax . _inputDomain . slice ( ) ;
48
+ else ax . _inputDomain = ax . domain . slice ( ) ;
49
+
47
50
if ( ! ax . _inputRange ) ax . _inputRange = ax . range . slice ( ) ;
48
51
49
52
// set axis scale here so we can use _m rather than
@@ -53,18 +56,19 @@ exports.enforce = function enforceAxisConstraints(gd) {
53
56
// abs: inverted scales still satisfy the constraint
54
57
normScales [ axisID ] = normScale = Math . abs ( ax . _m ) / group [ axisID ] ;
55
58
minScale = Math . min ( minScale , normScale ) ;
56
- if ( ax . _constraintShrinkable ) {
57
- // this has served its purpose, so remove it
58
- delete ax . _constraintShrinkable ;
59
- }
60
- else {
59
+ if ( ax . constrain === 'domain' || ! ax . _constraintShrinkable ) {
61
60
matchScale = Math . min ( matchScale , normScale ) ;
62
61
}
62
+
63
+ // this has served its purpose, so remove it
64
+ delete ax . _constraintShrinkable ;
63
65
maxScale = Math . max ( maxScale , normScale ) ;
66
+
67
+ if ( ax . constrain === 'domain' ) hasAnyDomainConstraint = true ;
64
68
}
65
69
66
70
// Do we have a constraint mismatch? Give a small buffer for rounding errors
67
- if ( minScale > ALMOST_EQUAL * maxScale ) continue ;
71
+ if ( minScale > ALMOST_EQUAL * maxScale && ! hasAnyDomainConstraint ) continue ;
68
72
69
73
// now increase any ranges we need to until all normalized scales are equal
70
74
for ( j = 0 ; j < axisIDs . length ; j ++ ) {
@@ -107,8 +111,7 @@ exports.enforce = function enforceAxisConstraints(gd) {
107
111
factor *= rangeShrunk ;
108
112
}
109
113
110
- // TODO
111
- if ( ax . autorange ) {
114
+ if ( ax . autorange && ax . _min . length && ax . _max . length ) {
112
115
/*
113
116
* range & factor may need to change because range was
114
117
* calculated for the larger scaling, so some pixel
@@ -121,12 +124,16 @@ exports.enforce = function enforceAxisConstraints(gd) {
121
124
* outerMin/Max are for - if the expansion was going to
122
125
* go beyond the original domain, it must be impossible
123
126
*/
124
- var rangeMin = Math . min ( ax . range [ 0 ] , ax . range [ 1 ] ) ;
125
- var rangeMax = Math . max ( ax . range [ 0 ] , ax . range [ 1 ] ) ;
126
- var rangeCenter = ( rangeMin + rangeMax ) / 2 ;
127
- var halfRange = rangeMax - rangeCenter ;
128
- var outerMin = rangeCenter - halfRange * factor ;
129
- var outerMax = rangeCenter + halfRange * factor ;
127
+ var rl0 = ax . r2l ( ax . range [ 0 ] ) ;
128
+ var rl1 = ax . r2l ( ax . range [ 1 ] ) ;
129
+ var rangeCenter = ( rl0 + rl1 ) / 2 ;
130
+ var rangeMin = rangeCenter ;
131
+ var rangeMax = rangeCenter ;
132
+ var halfRange = Math . abs ( rl1 - rangeCenter ) ;
133
+ // extra tiny bit for rounding errors, in case we actually
134
+ // *are* expanding to the full domain
135
+ var outerMin = rangeCenter - halfRange * factor * 1.0001 ;
136
+ var outerMax = rangeCenter + halfRange * factor * 1.0001 ;
130
137
131
138
updateDomain ( ax , factor ) ;
132
139
ax . setScale ( ) ;
@@ -135,34 +142,26 @@ exports.enforce = function enforceAxisConstraints(gd) {
135
142
var k ;
136
143
137
144
for ( k = 0 ; k < ax . _min . length ; k ++ ) {
138
- newVal = ax . _min [ i ] . val - ax . _min [ i ] . pad / m ;
145
+ newVal = ax . _min [ k ] . val - ax . _min [ k ] . pad / m ;
139
146
if ( newVal > outerMin && newVal < rangeMin ) {
140
147
rangeMin = newVal ;
141
148
}
142
149
}
143
150
144
151
for ( k = 0 ; k < ax . _max . length ; k ++ ) {
145
- newVal = ax . _max [ i ] . val + ax . _max [ i ] . pad / m ;
152
+ newVal = ax . _max [ k ] . val + ax . _max [ k ] . pad / m ;
146
153
if ( newVal < outerMax && newVal > rangeMax ) {
147
154
rangeMax = newVal ;
148
155
}
149
156
}
150
157
151
- ax . range = ax . _input . range = ( ax . range [ 0 ] < ax . range [ 1 ] ) ?
152
- [ rangeMin , rangeMax ] : [ rangeMax , rangeMin ] ;
153
-
154
- /*
155
- * In principle this new range can be shifted vs. what
156
- * you saw at the end of a zoom operation, like if you
157
- * have a big bubble on one side and a small bubble on
158
- * the other.
159
- * To fix this we'd have to be doing this calculation
160
- * continuously during the zoom, but it's enough of an
161
- * edge case and a subtle enough effect that I'm going
162
- * to ignore it for now.
163
- */
164
158
var domainExpand = ( rangeMax - rangeMin ) / ( 2 * halfRange ) ;
165
159
factor /= domainExpand ;
160
+
161
+ rangeMin = ax . l2r ( rangeMin ) ;
162
+ rangeMax = ax . l2r ( rangeMax ) ;
163
+ ax . range = ax . _input . range = ( rl0 < rl1 ) ?
164
+ [ rangeMin , rangeMax ] : [ rangeMax , rangeMin ] ;
166
165
}
167
166
168
167
updateDomain ( ax , factor ) ;
0 commit comments