11
11
12
12
var mouseChange = require ( 'mouse-change' ) ;
13
13
var mouseWheel = require ( 'mouse-wheel' ) ;
14
+ var cartesianConstants = require ( '../cartesian/constants' ) ;
14
15
15
16
module . exports = createCamera ;
16
17
@@ -22,8 +23,10 @@ function Camera2D(element, plot) {
22
23
this . lastInputTime = Date . now ( ) ;
23
24
this . lastPos = [ 0 , 0 ] ;
24
25
this . boxEnabled = false ;
26
+ this . boxInited = false ;
25
27
this . boxStart = [ 0 , 0 ] ;
26
28
this . boxEnd = [ 0 , 0 ] ;
29
+ this . dragStart = [ 0 , 0 ] ;
27
30
}
28
31
29
32
@@ -37,13 +40,33 @@ function createCamera(scene) {
37
40
scene . yaxis . autorange = false ;
38
41
}
39
42
43
+ function getSubplotConstraint ( ) {
44
+ // note: this assumes we only have one x and one y axis on this subplot
45
+ // when this constraint is lifted this block won't make sense
46
+ var constraints = scene . graphDiv . _fullLayout . _axisConstraintGroups ;
47
+ var xaId = scene . xaxis . _id ;
48
+ var yaId = scene . yaxis . _id ;
49
+ for ( var i = 0 ; i < constraints . length ; i ++ ) {
50
+ if ( constraints [ i ] [ xaId ] !== - 1 ) {
51
+ if ( constraints [ i ] [ yaId ] !== - 1 ) return true ;
52
+ break ;
53
+ }
54
+ }
55
+ return false ;
56
+ }
57
+
40
58
result . mouseListener = mouseChange ( element , function ( buttons , x , y ) {
41
59
var dataBox = scene . calcDataBox ( ) ,
42
60
viewBox = plot . viewBox ;
43
61
44
62
var lastX = result . lastPos [ 0 ] ,
45
63
lastY = result . lastPos [ 1 ] ;
46
64
65
+ var MINDRAG = cartesianConstants . MINDRAG * plot . pixelRatio ;
66
+ var MINZOOM = cartesianConstants . MINZOOM * plot . pixelRatio ;
67
+
68
+ var dx , dy ;
69
+
47
70
x *= plot . pixelRatio ;
48
71
y *= plot . pixelRatio ;
49
72
@@ -76,32 +99,114 @@ function createCamera(scene) {
76
99
( viewBox [ 3 ] - viewBox [ 1 ] ) * ( dataBox [ 3 ] - dataBox [ 1 ] ) +
77
100
dataBox [ 1 ] ;
78
101
79
- if ( ! result . boxEnabled ) {
102
+ if ( ! result . boxInited ) {
80
103
result . boxStart [ 0 ] = dataX ;
81
104
result . boxStart [ 1 ] = dataY ;
105
+ result . dragStart [ 0 ] = x ;
106
+ result . dragStart [ 1 ] = y ;
82
107
}
83
108
84
109
result . boxEnd [ 0 ] = dataX ;
85
110
result . boxEnd [ 1 ] = dataY ;
86
111
87
- result . boxEnabled = true ;
112
+ // we need to mark the box as initialized right away
113
+ // so that we can tell the start and end pionts apart
114
+ result . boxInited = true ;
115
+
116
+ // but don't actually enable the box until the cursor moves
117
+ if ( ! result . boxEnabled && (
118
+ result . boxStart [ 0 ] !== result . boxEnd [ 0 ] ||
119
+ result . boxStart [ 1 ] !== result . boxEnd [ 1 ] )
120
+ ) {
121
+ result . boxEnabled = true ;
122
+ }
123
+
124
+ // constrain aspect ratio if the axes require it
125
+ var smallDx = Math . abs ( result . dragStart [ 0 ] - x ) < MINZOOM ;
126
+ var smallDy = Math . abs ( result . dragStart [ 1 ] - y ) < MINZOOM ;
127
+ if ( getSubplotConstraint ( ) && ! ( smallDx && smallDy ) ) {
128
+ dx = result . boxEnd [ 0 ] - result . boxStart [ 0 ] ;
129
+ dy = result . boxEnd [ 1 ] - result . boxStart [ 1 ] ;
130
+ var dydx = ( dataBox [ 3 ] - dataBox [ 1 ] ) / ( dataBox [ 2 ] - dataBox [ 0 ] ) ;
131
+
132
+ if ( Math . abs ( dx * dydx ) > Math . abs ( dy ) ) {
133
+ result . boxEnd [ 1 ] = result . boxStart [ 1 ] +
134
+ Math . abs ( dx ) * dydx * ( Math . sign ( dy ) || 1 ) ;
135
+
136
+ // gl-select-box clips to the plot area bounds,
137
+ // which breaks the axis constraint, so don't allow
138
+ // this box to go out of bounds
139
+ if ( result . boxEnd [ 1 ] < dataBox [ 1 ] ) {
140
+ result . boxEnd [ 1 ] = dataBox [ 1 ] ;
141
+ result . boxEnd [ 0 ] = result . boxStart [ 0 ] +
142
+ ( dataBox [ 1 ] - result . boxStart [ 1 ] ) / Math . abs ( dydx ) ;
143
+ }
144
+ else if ( result . boxEnd [ 1 ] > dataBox [ 3 ] ) {
145
+ result . boxEnd [ 1 ] = dataBox [ 3 ] ;
146
+ result . boxEnd [ 0 ] = result . boxStart [ 0 ] +
147
+ ( dataBox [ 3 ] - result . boxStart [ 1 ] ) / Math . abs ( dydx ) ;
148
+ }
149
+ }
150
+ else {
151
+ result . boxEnd [ 0 ] = result . boxStart [ 0 ] +
152
+ Math . abs ( dy ) / dydx * ( Math . sign ( dx ) || 1 ) ;
153
+
154
+ if ( result . boxEnd [ 0 ] < dataBox [ 0 ] ) {
155
+ result . boxEnd [ 0 ] = dataBox [ 0 ] ;
156
+ result . boxEnd [ 1 ] = result . boxStart [ 1 ] +
157
+ ( dataBox [ 0 ] - result . boxStart [ 0 ] ) * Math . abs ( dydx ) ;
158
+ }
159
+ else if ( result . boxEnd [ 0 ] > dataBox [ 2 ] ) {
160
+ result . boxEnd [ 0 ] = dataBox [ 2 ] ;
161
+ result . boxEnd [ 1 ] = result . boxStart [ 1 ] +
162
+ ( dataBox [ 2 ] - result . boxStart [ 0 ] ) * Math . abs ( dydx ) ;
163
+ }
164
+ }
165
+ }
166
+ // otherwise clamp small changes to the origin so we get 1D zoom
167
+ else {
168
+ if ( smallDx ) result . boxEnd [ 0 ] = result . boxStart [ 0 ] ;
169
+ if ( smallDy ) result . boxEnd [ 1 ] = result . boxStart [ 1 ] ;
170
+ }
88
171
}
89
172
else if ( result . boxEnabled ) {
90
- updateRange ( 0 , result . boxStart [ 0 ] , result . boxEnd [ 0 ] ) ;
91
- updateRange ( 1 , result . boxStart [ 1 ] , result . boxEnd [ 1 ] ) ;
92
- unSetAutoRange ( ) ;
173
+ dx = result . boxStart [ 0 ] !== result . boxEnd [ 0 ] ;
174
+ dy = result . boxStart [ 1 ] !== result . boxEnd [ 1 ] ;
175
+ if ( dx || dy ) {
176
+ if ( dx ) {
177
+ updateRange ( 0 , result . boxStart [ 0 ] , result . boxEnd [ 0 ] ) ;
178
+ scene . xaxis . autorange = false ;
179
+ }
180
+ if ( dy ) {
181
+ updateRange ( 1 , result . boxStart [ 1 ] , result . boxEnd [ 1 ] ) ;
182
+ scene . yaxis . autorange = false ;
183
+ }
184
+ scene . relayoutCallback ( ) ;
185
+ }
186
+ else {
187
+ scene . glplot . setDirty ( ) ;
188
+ }
93
189
result . boxEnabled = false ;
94
- scene . relayoutCallback ( ) ;
190
+ result . boxInited = false ;
95
191
}
96
192
break ;
97
193
98
194
case 'pan' :
99
195
result . boxEnabled = false ;
196
+ result . boxInited = false ;
100
197
101
198
if ( buttons ) {
102
- var dx = ( lastX - x ) * ( dataBox [ 2 ] - dataBox [ 0 ] ) /
199
+ if ( ! result . panning ) {
200
+ result . dragStart [ 0 ] = x ;
201
+ result . dragStart [ 1 ] = y ;
202
+ }
203
+
204
+ if ( Math . abs ( result . dragStart [ 0 ] - x ) < MINDRAG ) x = result . dragStart [ 0 ] ;
205
+ if ( Math . abs ( result . dragStart [ 1 ] - y ) < MINDRAG ) y = result . dragStart [ 1 ] ;
206
+
207
+ dx = ( lastX - x ) * ( dataBox [ 2 ] - dataBox [ 0 ] ) /
103
208
( plot . viewBox [ 2 ] - plot . viewBox [ 0 ] ) ;
104
- var dy = ( lastY - y ) * ( dataBox [ 3 ] - dataBox [ 1 ] ) /
209
+ dy = ( lastY - y ) * ( dataBox [ 3 ] - dataBox [ 1 ] ) /
105
210
( plot . viewBox [ 3 ] - plot . viewBox [ 1 ] ) ;
106
211
107
212
dataBox [ 0 ] += dx ;
0 commit comments