TrackballControls.js 16.8 KB
Newer Older
M
r101  
Mr.doob 已提交
1 2
import {
	EventDispatcher,
M
r107  
Mr.doob 已提交
3
	MOUSE,
M
r101  
Mr.doob 已提交
4 5 6
	Quaternion,
	Vector2,
	Vector3
M
r124  
Mr.doob 已提交
7
} from '../../../build/three.module.js';
M
r101  
Mr.doob 已提交
8

M
r128  
Mr.doob 已提交
9 10 11
const _changeEvent = { type: 'change' };
const _startEvent = { type: 'start' };
const _endEvent = { type: 'end' };
M
r101  
Mr.doob 已提交
12

M
r128  
Mr.doob 已提交
13
class TrackballControls extends EventDispatcher {
M
r110  
Mr.doob 已提交
14

M
r128  
Mr.doob 已提交
15
	constructor( object, domElement ) {
M
r101  
Mr.doob 已提交
16

M
r128  
Mr.doob 已提交
17
		super();
M
r101  
Mr.doob 已提交
18

M
r128  
Mr.doob 已提交
19 20
		if ( domElement === undefined ) console.warn( 'THREE.TrackballControls: The second parameter "domElement" is now mandatory.' );
		if ( domElement === document ) console.error( 'THREE.TrackballControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
M
r101  
Mr.doob 已提交
21

M
r128  
Mr.doob 已提交
22 23
		const scope = this;
		const STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
M
r101  
Mr.doob 已提交
24

M
r128  
Mr.doob 已提交
25 26
		this.object = object;
		this.domElement = domElement;
M
r130  
Mr.doob 已提交
27
		this.domElement.style.touchAction = 'none'; // disable touch scroll
M
r101  
Mr.doob 已提交
28

M
r128  
Mr.doob 已提交
29
		// API
M
r101  
Mr.doob 已提交
30

M
r128  
Mr.doob 已提交
31
		this.enabled = true;
M
r101  
Mr.doob 已提交
32

M
r128  
Mr.doob 已提交
33
		this.screen = { left: 0, top: 0, width: 0, height: 0 };
M
r101  
Mr.doob 已提交
34

M
r128  
Mr.doob 已提交
35 36 37
		this.rotateSpeed = 1.0;
		this.zoomSpeed = 1.2;
		this.panSpeed = 0.3;
M
r101  
Mr.doob 已提交
38

M
r128  
Mr.doob 已提交
39 40 41
		this.noRotate = false;
		this.noZoom = false;
		this.noPan = false;
M
r101  
Mr.doob 已提交
42

M
r128  
Mr.doob 已提交
43 44
		this.staticMoving = false;
		this.dynamicDampingFactor = 0.2;
M
r107  
Mr.doob 已提交
45

M
r128  
Mr.doob 已提交
46 47
		this.minDistance = 0;
		this.maxDistance = Infinity;
M
r101  
Mr.doob 已提交
48

M
r128  
Mr.doob 已提交
49
		this.keys = [ 'KeyA' /*A*/, 'KeyS' /*S*/, 'KeyD' /*D*/ ];
M
r101  
Mr.doob 已提交
50

M
r128  
Mr.doob 已提交
51
		this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
M
r101  
Mr.doob 已提交
52

M
r128  
Mr.doob 已提交
53
		// internals
M
r101  
Mr.doob 已提交
54

M
r128  
Mr.doob 已提交
55
		this.target = new Vector3();
M
r101  
Mr.doob 已提交
56

M
r128  
Mr.doob 已提交
57
		const EPS = 0.000001;
M
r101  
Mr.doob 已提交
58

M
r128  
Mr.doob 已提交
59 60
		const lastPosition = new Vector3();
		let lastZoom = 1;
M
r101  
Mr.doob 已提交
61

M
r128  
Mr.doob 已提交
62 63
		let _state = STATE.NONE,
			_keyState = STATE.NONE,
M
r101  
Mr.doob 已提交
64

M
r128  
Mr.doob 已提交
65 66
			_touchZoomDistanceStart = 0,
			_touchZoomDistanceEnd = 0,
M
r101  
Mr.doob 已提交
67

M
r128  
Mr.doob 已提交
68
			_lastAngle = 0;
M
r101  
Mr.doob 已提交
69

M
r128  
Mr.doob 已提交
70
		const _eye = new Vector3(),
M
r101  
Mr.doob 已提交
71

M
r128  
Mr.doob 已提交
72 73
			_movePrev = new Vector2(),
			_moveCurr = new Vector2(),
M
r101  
Mr.doob 已提交
74

M
r128  
Mr.doob 已提交
75
			_lastAxis = new Vector3(),
M
r101  
Mr.doob 已提交
76

M
r128  
Mr.doob 已提交
77 78
			_zoomStart = new Vector2(),
			_zoomEnd = new Vector2(),
M
r101  
Mr.doob 已提交
79

M
r128  
Mr.doob 已提交
80
			_panStart = new Vector2(),
M
r130  
Mr.doob 已提交
81 82 83 84
			_panEnd = new Vector2(),

			_pointers = [],
			_pointerPositions = {};
M
r101  
Mr.doob 已提交
85

M
r128  
Mr.doob 已提交
86
		// for reset
M
r101  
Mr.doob 已提交
87

M
r128  
Mr.doob 已提交
88 89 90 91
		this.target0 = this.target.clone();
		this.position0 = this.object.position.clone();
		this.up0 = this.object.up.clone();
		this.zoom0 = this.object.zoom;
M
r101  
Mr.doob 已提交
92

M
r128  
Mr.doob 已提交
93
		// methods
M
r101  
Mr.doob 已提交
94

M
r128  
Mr.doob 已提交
95
		this.handleResize = function () {
M
r101  
Mr.doob 已提交
96

M
r128  
Mr.doob 已提交
97 98 99 100 101 102 103
			const box = scope.domElement.getBoundingClientRect();
			// adjustments come from similar code in the jquery offset() function
			const d = scope.domElement.ownerDocument.documentElement;
			scope.screen.left = box.left + window.pageXOffset - d.clientLeft;
			scope.screen.top = box.top + window.pageYOffset - d.clientTop;
			scope.screen.width = box.width;
			scope.screen.height = box.height;
M
r101  
Mr.doob 已提交
104

M
r128  
Mr.doob 已提交
105
		};
M
r101  
Mr.doob 已提交
106

M
r128  
Mr.doob 已提交
107
		const getMouseOnScreen = ( function () {
M
r101  
Mr.doob 已提交
108

M
r128  
Mr.doob 已提交
109
			const vector = new Vector2();
M
r101  
Mr.doob 已提交
110

M
r128  
Mr.doob 已提交
111
			return function getMouseOnScreen( pageX, pageY ) {
M
r101  
Mr.doob 已提交
112

M
r128  
Mr.doob 已提交
113 114 115 116
				vector.set(
					( pageX - scope.screen.left ) / scope.screen.width,
					( pageY - scope.screen.top ) / scope.screen.height
				);
M
r101  
Mr.doob 已提交
117

M
r128  
Mr.doob 已提交
118
				return vector;
M
r101  
Mr.doob 已提交
119

M
r128  
Mr.doob 已提交
120
			};
M
r101  
Mr.doob 已提交
121

M
r128  
Mr.doob 已提交
122
		}() );
M
r101  
Mr.doob 已提交
123

M
r128  
Mr.doob 已提交
124
		const getMouseOnCircle = ( function () {
M
r101  
Mr.doob 已提交
125

M
r128  
Mr.doob 已提交
126
			const vector = new Vector2();
M
r101  
Mr.doob 已提交
127

M
r128  
Mr.doob 已提交
128
			return function getMouseOnCircle( pageX, pageY ) {
M
r101  
Mr.doob 已提交
129

M
r128  
Mr.doob 已提交
130 131 132 133
				vector.set(
					( ( pageX - scope.screen.width * 0.5 - scope.screen.left ) / ( scope.screen.width * 0.5 ) ),
					( ( scope.screen.height + 2 * ( scope.screen.top - pageY ) ) / scope.screen.width ) // screen.width intentional
				);
M
r101  
Mr.doob 已提交
134

M
r128  
Mr.doob 已提交
135
				return vector;
M
r101  
Mr.doob 已提交
136

M
r128  
Mr.doob 已提交
137
			};
M
r101  
Mr.doob 已提交
138

M
r128  
Mr.doob 已提交
139
		}() );
M
r101  
Mr.doob 已提交
140

M
r128  
Mr.doob 已提交
141
		this.rotateCamera = ( function () {
M
r101  
Mr.doob 已提交
142

M
r128  
Mr.doob 已提交
143 144 145 146 147 148
			const axis = new Vector3(),
				quaternion = new Quaternion(),
				eyeDirection = new Vector3(),
				objectUpDirection = new Vector3(),
				objectSidewaysDirection = new Vector3(),
				moveDirection = new Vector3();
M
r101  
Mr.doob 已提交
149

M
r128  
Mr.doob 已提交
150
			return function rotateCamera() {
M
r101  
Mr.doob 已提交
151

M
r128  
Mr.doob 已提交
152 153
				moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
				let angle = moveDirection.length();
M
r101  
Mr.doob 已提交
154

M
r128  
Mr.doob 已提交
155
				if ( angle ) {
M
r101  
Mr.doob 已提交
156

M
r128  
Mr.doob 已提交
157
					_eye.copy( scope.object.position ).sub( scope.target );
M
r101  
Mr.doob 已提交
158

M
r128  
Mr.doob 已提交
159 160 161
					eyeDirection.copy( _eye ).normalize();
					objectUpDirection.copy( scope.object.up ).normalize();
					objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
M
r101  
Mr.doob 已提交
162

M
r128  
Mr.doob 已提交
163 164
					objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
					objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
M
r101  
Mr.doob 已提交
165

M
r128  
Mr.doob 已提交
166
					moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
M
r101  
Mr.doob 已提交
167

M
r128  
Mr.doob 已提交
168
					axis.crossVectors( moveDirection, _eye ).normalize();
M
r101  
Mr.doob 已提交
169

M
r128  
Mr.doob 已提交
170 171
					angle *= scope.rotateSpeed;
					quaternion.setFromAxisAngle( axis, angle );
M
r101  
Mr.doob 已提交
172

M
r128  
Mr.doob 已提交
173 174
					_eye.applyQuaternion( quaternion );
					scope.object.up.applyQuaternion( quaternion );
M
r101  
Mr.doob 已提交
175

M
r128  
Mr.doob 已提交
176 177
					_lastAxis.copy( axis );
					_lastAngle = angle;
M
r101  
Mr.doob 已提交
178

M
r128  
Mr.doob 已提交
179
				} else if ( ! scope.staticMoving && _lastAngle ) {
M
r101  
Mr.doob 已提交
180

M
r128  
Mr.doob 已提交
181 182 183 184 185
					_lastAngle *= Math.sqrt( 1.0 - scope.dynamicDampingFactor );
					_eye.copy( scope.object.position ).sub( scope.target );
					quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
					_eye.applyQuaternion( quaternion );
					scope.object.up.applyQuaternion( quaternion );
M
r101  
Mr.doob 已提交
186

M
r128  
Mr.doob 已提交
187
				}
M
r101  
Mr.doob 已提交
188

M
r128  
Mr.doob 已提交
189
				_movePrev.copy( _moveCurr );
M
r101  
Mr.doob 已提交
190

M
r128  
Mr.doob 已提交
191
			};
M
r101  
Mr.doob 已提交
192

M
r128  
Mr.doob 已提交
193
		}() );
M
r101  
Mr.doob 已提交
194 195


M
r128  
Mr.doob 已提交
196
		this.zoomCamera = function () {
M
r101  
Mr.doob 已提交
197

M
r128  
Mr.doob 已提交
198
			let factor;
M
r101  
Mr.doob 已提交
199

M
r128  
Mr.doob 已提交
200
			if ( _state === STATE.TOUCH_ZOOM_PAN ) {
M
r109  
Mr.doob 已提交
201

M
r128  
Mr.doob 已提交
202 203
				factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
				_touchZoomDistanceStart = _touchZoomDistanceEnd;
M
r109  
Mr.doob 已提交
204

M
r128  
Mr.doob 已提交
205
				if ( scope.object.isPerspectiveCamera ) {
M
r109  
Mr.doob 已提交
206

M
r128  
Mr.doob 已提交
207
					_eye.multiplyScalar( factor );
M
r109  
Mr.doob 已提交
208

M
r128  
Mr.doob 已提交
209
				} else if ( scope.object.isOrthographicCamera ) {
M
r109  
Mr.doob 已提交
210

M
r128  
Mr.doob 已提交
211 212
					scope.object.zoom *= factor;
					scope.object.updateProjectionMatrix();
M
r109  
Mr.doob 已提交
213

M
r128  
Mr.doob 已提交
214
				} else {
M
r109  
Mr.doob 已提交
215

M
r128  
Mr.doob 已提交
216
					console.warn( 'THREE.TrackballControls: Unsupported camera type' );
M
r101  
Mr.doob 已提交
217

M
r128  
Mr.doob 已提交
218
				}
M
r101  
Mr.doob 已提交
219

M
r128  
Mr.doob 已提交
220
			} else {
M
r101  
Mr.doob 已提交
221

M
r128  
Mr.doob 已提交
222
				factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * scope.zoomSpeed;
M
r101  
Mr.doob 已提交
223

M
r128  
Mr.doob 已提交
224
				if ( factor !== 1.0 && factor > 0.0 ) {
M
r109  
Mr.doob 已提交
225

M
r128  
Mr.doob 已提交
226
					if ( scope.object.isPerspectiveCamera ) {
M
r109  
Mr.doob 已提交
227

M
r128  
Mr.doob 已提交
228
						_eye.multiplyScalar( factor );
M
r109  
Mr.doob 已提交
229

M
r128  
Mr.doob 已提交
230
					} else if ( scope.object.isOrthographicCamera ) {
M
r109  
Mr.doob 已提交
231

M
r128  
Mr.doob 已提交
232 233
						scope.object.zoom /= factor;
						scope.object.updateProjectionMatrix();
M
r109  
Mr.doob 已提交
234

M
r128  
Mr.doob 已提交
235 236 237 238 239
					} else {

						console.warn( 'THREE.TrackballControls: Unsupported camera type' );

					}
M
r109  
Mr.doob 已提交
240 241

				}
M
r101  
Mr.doob 已提交
242

M
r128  
Mr.doob 已提交
243
				if ( scope.staticMoving ) {
M
r101  
Mr.doob 已提交
244

M
r128  
Mr.doob 已提交
245
					_zoomStart.copy( _zoomEnd );
M
r101  
Mr.doob 已提交
246

M
r128  
Mr.doob 已提交
247
				} else {
M
r101  
Mr.doob 已提交
248

M
r128  
Mr.doob 已提交
249
					_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
M
r101  
Mr.doob 已提交
250

M
r128  
Mr.doob 已提交
251
				}
M
r101  
Mr.doob 已提交
252 253 254

			}

M
r128  
Mr.doob 已提交
255
		};
M
r101  
Mr.doob 已提交
256

M
r128  
Mr.doob 已提交
257
		this.panCamera = ( function () {
M
r101  
Mr.doob 已提交
258

M
r128  
Mr.doob 已提交
259 260 261
			const mouseChange = new Vector2(),
				objectUp = new Vector3(),
				pan = new Vector3();
M
r101  
Mr.doob 已提交
262

M
r128  
Mr.doob 已提交
263
			return function panCamera() {
M
r101  
Mr.doob 已提交
264

M
r128  
Mr.doob 已提交
265
				mouseChange.copy( _panEnd ).sub( _panStart );
M
r101  
Mr.doob 已提交
266

M
r128  
Mr.doob 已提交
267
				if ( mouseChange.lengthSq() ) {
M
r101  
Mr.doob 已提交
268

M
r128  
Mr.doob 已提交
269
					if ( scope.object.isOrthographicCamera ) {
M
r101  
Mr.doob 已提交
270

M
r128  
Mr.doob 已提交
271 272
						const scale_x = ( scope.object.right - scope.object.left ) / scope.object.zoom / scope.domElement.clientWidth;
						const scale_y = ( scope.object.top - scope.object.bottom ) / scope.object.zoom / scope.domElement.clientWidth;
M
r109  
Mr.doob 已提交
273

M
r128  
Mr.doob 已提交
274 275
						mouseChange.x *= scale_x;
						mouseChange.y *= scale_y;
M
r109  
Mr.doob 已提交
276

M
r128  
Mr.doob 已提交
277
					}
M
r109  
Mr.doob 已提交
278

M
r128  
Mr.doob 已提交
279
					mouseChange.multiplyScalar( _eye.length() * scope.panSpeed );
M
r109  
Mr.doob 已提交
280

M
r128  
Mr.doob 已提交
281 282
					pan.copy( _eye ).cross( scope.object.up ).setLength( mouseChange.x );
					pan.add( objectUp.copy( scope.object.up ).setLength( mouseChange.y ) );
M
r101  
Mr.doob 已提交
283

M
r128  
Mr.doob 已提交
284 285
					scope.object.position.add( pan );
					scope.target.add( pan );
M
r101  
Mr.doob 已提交
286

M
r128  
Mr.doob 已提交
287
					if ( scope.staticMoving ) {
M
r101  
Mr.doob 已提交
288

M
r128  
Mr.doob 已提交
289
						_panStart.copy( _panEnd );
M
r101  
Mr.doob 已提交
290

M
r128  
Mr.doob 已提交
291
					} else {
M
r101  
Mr.doob 已提交
292

M
r128  
Mr.doob 已提交
293
						_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( scope.dynamicDampingFactor ) );
M
r101  
Mr.doob 已提交
294

M
r128  
Mr.doob 已提交
295
					}
M
r101  
Mr.doob 已提交
296 297 298

				}

M
r128  
Mr.doob 已提交
299
			};
M
r101  
Mr.doob 已提交
300

M
r128  
Mr.doob 已提交
301
		}() );
M
r101  
Mr.doob 已提交
302

M
r128  
Mr.doob 已提交
303
		this.checkDistances = function () {
M
r101  
Mr.doob 已提交
304

M
r128  
Mr.doob 已提交
305
			if ( ! scope.noZoom || ! scope.noPan ) {
M
r101  
Mr.doob 已提交
306

M
r128  
Mr.doob 已提交
307
				if ( _eye.lengthSq() > scope.maxDistance * scope.maxDistance ) {
M
r101  
Mr.doob 已提交
308

M
r128  
Mr.doob 已提交
309 310
					scope.object.position.addVectors( scope.target, _eye.setLength( scope.maxDistance ) );
					_zoomStart.copy( _zoomEnd );
M
r101  
Mr.doob 已提交
311

M
r128  
Mr.doob 已提交
312
				}
M
r101  
Mr.doob 已提交
313

M
r128  
Mr.doob 已提交
314
				if ( _eye.lengthSq() < scope.minDistance * scope.minDistance ) {
M
r101  
Mr.doob 已提交
315

M
r128  
Mr.doob 已提交
316 317
					scope.object.position.addVectors( scope.target, _eye.setLength( scope.minDistance ) );
					_zoomStart.copy( _zoomEnd );
M
r101  
Mr.doob 已提交
318

M
r128  
Mr.doob 已提交
319
				}
M
r101  
Mr.doob 已提交
320 321 322

			}

M
r128  
Mr.doob 已提交
323
		};
M
r101  
Mr.doob 已提交
324

M
r128  
Mr.doob 已提交
325
		this.update = function () {
M
r101  
Mr.doob 已提交
326

M
r128  
Mr.doob 已提交
327
			_eye.subVectors( scope.object.position, scope.target );
M
r101  
Mr.doob 已提交
328

M
r128  
Mr.doob 已提交
329
			if ( ! scope.noRotate ) {
M
r101  
Mr.doob 已提交
330

M
r128  
Mr.doob 已提交
331
				scope.rotateCamera();
M
r101  
Mr.doob 已提交
332

M
r128  
Mr.doob 已提交
333
			}
M
r101  
Mr.doob 已提交
334

M
r128  
Mr.doob 已提交
335
			if ( ! scope.noZoom ) {
M
r101  
Mr.doob 已提交
336

M
r128  
Mr.doob 已提交
337
				scope.zoomCamera();
M
r101  
Mr.doob 已提交
338

M
r128  
Mr.doob 已提交
339
			}
M
r101  
Mr.doob 已提交
340

M
r128  
Mr.doob 已提交
341
			if ( ! scope.noPan ) {
M
r101  
Mr.doob 已提交
342

M
r128  
Mr.doob 已提交
343
				scope.panCamera();
M
r101  
Mr.doob 已提交
344

M
r128  
Mr.doob 已提交
345
			}
M
r101  
Mr.doob 已提交
346

M
r128  
Mr.doob 已提交
347
			scope.object.position.addVectors( scope.target, _eye );
M
r101  
Mr.doob 已提交
348

M
r128  
Mr.doob 已提交
349
			if ( scope.object.isPerspectiveCamera ) {
M
r101  
Mr.doob 已提交
350

M
r128  
Mr.doob 已提交
351
				scope.checkDistances();
M
r101  
Mr.doob 已提交
352

M
r128  
Mr.doob 已提交
353
				scope.object.lookAt( scope.target );
M
r101  
Mr.doob 已提交
354

M
r128  
Mr.doob 已提交
355
				if ( lastPosition.distanceToSquared( scope.object.position ) > EPS ) {
M
r109  
Mr.doob 已提交
356

M
r128  
Mr.doob 已提交
357
					scope.dispatchEvent( _changeEvent );
M
r109  
Mr.doob 已提交
358

M
r128  
Mr.doob 已提交
359
					lastPosition.copy( scope.object.position );
M
r109  
Mr.doob 已提交
360

M
r128  
Mr.doob 已提交
361
				}
M
r109  
Mr.doob 已提交
362

M
r128  
Mr.doob 已提交
363
			} else if ( scope.object.isOrthographicCamera ) {
M
r101  
Mr.doob 已提交
364

M
r128  
Mr.doob 已提交
365
				scope.object.lookAt( scope.target );
M
r101  
Mr.doob 已提交
366

M
r128  
Mr.doob 已提交
367
				if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || lastZoom !== scope.object.zoom ) {
M
r109  
Mr.doob 已提交
368

M
r128  
Mr.doob 已提交
369
					scope.dispatchEvent( _changeEvent );
M
r109  
Mr.doob 已提交
370

M
r128  
Mr.doob 已提交
371 372
					lastPosition.copy( scope.object.position );
					lastZoom = scope.object.zoom;
M
r109  
Mr.doob 已提交
373

M
r128  
Mr.doob 已提交
374
				}
M
r109  
Mr.doob 已提交
375

M
r128  
Mr.doob 已提交
376
			} else {
M
r109  
Mr.doob 已提交
377

M
r128  
Mr.doob 已提交
378
				console.warn( 'THREE.TrackballControls: Unsupported camera type' );
M
r109  
Mr.doob 已提交
379

M
r128  
Mr.doob 已提交
380
			}
M
r101  
Mr.doob 已提交
381

M
r128  
Mr.doob 已提交
382
		};
M
r101  
Mr.doob 已提交
383

M
r128  
Mr.doob 已提交
384
		this.reset = function () {
M
r101  
Mr.doob 已提交
385

M
r128  
Mr.doob 已提交
386 387
			_state = STATE.NONE;
			_keyState = STATE.NONE;
M
r101  
Mr.doob 已提交
388

M
r128  
Mr.doob 已提交
389 390 391 392
			scope.target.copy( scope.target0 );
			scope.object.position.copy( scope.position0 );
			scope.object.up.copy( scope.up0 );
			scope.object.zoom = scope.zoom0;
M
r101  
Mr.doob 已提交
393

M
r128  
Mr.doob 已提交
394
			scope.object.updateProjectionMatrix();
M
r109  
Mr.doob 已提交
395

M
r128  
Mr.doob 已提交
396
			_eye.subVectors( scope.object.position, scope.target );
M
r101  
Mr.doob 已提交
397

M
r128  
Mr.doob 已提交
398
			scope.object.lookAt( scope.target );
M
r101  
Mr.doob 已提交
399

M
r128  
Mr.doob 已提交
400
			scope.dispatchEvent( _changeEvent );
M
r101  
Mr.doob 已提交
401

M
r128  
Mr.doob 已提交
402 403
			lastPosition.copy( scope.object.position );
			lastZoom = scope.object.zoom;
M
r101  
Mr.doob 已提交
404

M
r128  
Mr.doob 已提交
405
		};
M
r101  
Mr.doob 已提交
406

M
r128  
Mr.doob 已提交
407
		// listeners
M
r101  
Mr.doob 已提交
408

M
r128  
Mr.doob 已提交
409
		function onPointerDown( event ) {
M
r101  
Mr.doob 已提交
410

M
r128  
Mr.doob 已提交
411
			if ( scope.enabled === false ) return;
M
r120  
Mr.doob 已提交
412

M
r130  
Mr.doob 已提交
413
			if ( _pointers.length === 0 ) {
M
r120  
Mr.doob 已提交
414

M
r130  
Mr.doob 已提交
415 416 417 418 419 420 421 422
				scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
				scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );

			}

			//

			addPointer( event );
M
r120  
Mr.doob 已提交
423

M
r130  
Mr.doob 已提交
424 425 426 427 428 429 430
			if ( event.pointerType === 'touch' ) {

				onTouchStart( event );

			} else {

				onMouseDown( event );
M
r120  
Mr.doob 已提交
431

M
r128  
Mr.doob 已提交
432
			}
M
r120  
Mr.doob 已提交
433 434 435

		}

M
r128  
Mr.doob 已提交
436
		function onPointerMove( event ) {
M
r120  
Mr.doob 已提交
437

M
r128  
Mr.doob 已提交
438
			if ( scope.enabled === false ) return;
M
r120  
Mr.doob 已提交
439

M
r130  
Mr.doob 已提交
440
			if ( event.pointerType === 'touch' ) {
M
r120  
Mr.doob 已提交
441

M
r130  
Mr.doob 已提交
442
				onTouchMove( event );
M
r120  
Mr.doob 已提交
443

M
r130  
Mr.doob 已提交
444 445 446
			} else {

				onMouseMove( event );
M
r120  
Mr.doob 已提交
447

M
r128  
Mr.doob 已提交
448
			}
M
r120  
Mr.doob 已提交
449 450 451

		}

M
r128  
Mr.doob 已提交
452
		function onPointerUp( event ) {
M
r120  
Mr.doob 已提交
453

M
r128  
Mr.doob 已提交
454
			if ( scope.enabled === false ) return;
M
r120  
Mr.doob 已提交
455

M
r130  
Mr.doob 已提交
456
			if ( event.pointerType === 'touch' ) {
M
r120  
Mr.doob 已提交
457

M
r130  
Mr.doob 已提交
458 459 460
				onTouchEnd( event );

			} else {
M
r120  
Mr.doob 已提交
461

M
r130  
Mr.doob 已提交
462
				onMouseUp();
M
r120  
Mr.doob 已提交
463

M
r128  
Mr.doob 已提交
464
			}
M
r120  
Mr.doob 已提交
465

M
r130  
Mr.doob 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
			//

			removePointer( event );

			if ( _pointers.length === 0 ) {

				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );

			}


		}

		function onPointerCancel( event ) {

			removePointer( event );

M
r120  
Mr.doob 已提交
484 485
		}

M
r128  
Mr.doob 已提交
486
		function keydown( event ) {
M
r120  
Mr.doob 已提交
487

M
r128  
Mr.doob 已提交
488
			if ( scope.enabled === false ) return;
M
r101  
Mr.doob 已提交
489

M
r128  
Mr.doob 已提交
490
			window.removeEventListener( 'keydown', keydown );
M
r101  
Mr.doob 已提交
491

M
r128  
Mr.doob 已提交
492
			if ( _keyState !== STATE.NONE ) {
M
r101  
Mr.doob 已提交
493

M
r128  
Mr.doob 已提交
494
				return;
M
r101  
Mr.doob 已提交
495

M
r128  
Mr.doob 已提交
496
			} else if ( event.code === scope.keys[ STATE.ROTATE ] && ! scope.noRotate ) {
M
r101  
Mr.doob 已提交
497

M
r128  
Mr.doob 已提交
498
				_keyState = STATE.ROTATE;
M
r101  
Mr.doob 已提交
499

M
r128  
Mr.doob 已提交
500
			} else if ( event.code === scope.keys[ STATE.ZOOM ] && ! scope.noZoom ) {
M
r101  
Mr.doob 已提交
501

M
r128  
Mr.doob 已提交
502
				_keyState = STATE.ZOOM;
M
r101  
Mr.doob 已提交
503

M
r128  
Mr.doob 已提交
504
			} else if ( event.code === scope.keys[ STATE.PAN ] && ! scope.noPan ) {
M
r101  
Mr.doob 已提交
505

M
r128  
Mr.doob 已提交
506
				_keyState = STATE.PAN;
M
r101  
Mr.doob 已提交
507

M
r128  
Mr.doob 已提交
508
			}
M
r101  
Mr.doob 已提交
509 510 511

		}

M
r128  
Mr.doob 已提交
512
		function keyup() {
M
r101  
Mr.doob 已提交
513

M
r128  
Mr.doob 已提交
514
			if ( scope.enabled === false ) return;
M
r101  
Mr.doob 已提交
515

M
r128  
Mr.doob 已提交
516
			_keyState = STATE.NONE;
M
r101  
Mr.doob 已提交
517

M
r128  
Mr.doob 已提交
518
			window.addEventListener( 'keydown', keydown );
M
r101  
Mr.doob 已提交
519

M
r128  
Mr.doob 已提交
520
		}
M
r101  
Mr.doob 已提交
521

M
r128  
Mr.doob 已提交
522
		function onMouseDown( event ) {
M
r101  
Mr.doob 已提交
523

M
r128  
Mr.doob 已提交
524
			if ( _state === STATE.NONE ) {
M
r101  
Mr.doob 已提交
525

M
r128  
Mr.doob 已提交
526
				switch ( event.button ) {
M
r101  
Mr.doob 已提交
527

M
r128  
Mr.doob 已提交
528 529 530
					case scope.mouseButtons.LEFT:
						_state = STATE.ROTATE;
						break;
M
r107  
Mr.doob 已提交
531

M
r128  
Mr.doob 已提交
532 533 534
					case scope.mouseButtons.MIDDLE:
						_state = STATE.ZOOM;
						break;
M
r107  
Mr.doob 已提交
535

M
r128  
Mr.doob 已提交
536 537 538
					case scope.mouseButtons.RIGHT:
						_state = STATE.PAN;
						break;
M
r107  
Mr.doob 已提交
539

M
r128  
Mr.doob 已提交
540 541
					default:
						_state = STATE.NONE;
M
r107  
Mr.doob 已提交
542

M
r128  
Mr.doob 已提交
543
				}
M
r107  
Mr.doob 已提交
544 545

			}
M
r101  
Mr.doob 已提交
546

M
r128  
Mr.doob 已提交
547
			const state = ( _keyState !== STATE.NONE ) ? _keyState : _state;
M
r101  
Mr.doob 已提交
548

M
r128  
Mr.doob 已提交
549
			if ( state === STATE.ROTATE && ! scope.noRotate ) {
M
r107  
Mr.doob 已提交
550

M
r128  
Mr.doob 已提交
551 552
				_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
				_movePrev.copy( _moveCurr );
M
r101  
Mr.doob 已提交
553

M
r128  
Mr.doob 已提交
554
			} else if ( state === STATE.ZOOM && ! scope.noZoom ) {
M
r101  
Mr.doob 已提交
555

M
r128  
Mr.doob 已提交
556 557
				_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
				_zoomEnd.copy( _zoomStart );
M
r101  
Mr.doob 已提交
558

M
r128  
Mr.doob 已提交
559
			} else if ( state === STATE.PAN && ! scope.noPan ) {
M
r101  
Mr.doob 已提交
560

M
r128  
Mr.doob 已提交
561 562
				_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
				_panEnd.copy( _panStart );
M
r101  
Mr.doob 已提交
563

M
r128  
Mr.doob 已提交
564
			}
M
r101  
Mr.doob 已提交
565

M
r128  
Mr.doob 已提交
566 567
			scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
			scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
M
r101  
Mr.doob 已提交
568

M
r128  
Mr.doob 已提交
569
			scope.dispatchEvent( _startEvent );
M
r101  
Mr.doob 已提交
570

M
r128  
Mr.doob 已提交
571
		}
M
r120  
Mr.doob 已提交
572

M
r128  
Mr.doob 已提交
573
		function onMouseMove( event ) {
M
r101  
Mr.doob 已提交
574

M
r128  
Mr.doob 已提交
575
			const state = ( _keyState !== STATE.NONE ) ? _keyState : _state;
M
r101  
Mr.doob 已提交
576

M
r128  
Mr.doob 已提交
577
			if ( state === STATE.ROTATE && ! scope.noRotate ) {
M
r107  
Mr.doob 已提交
578

M
r128  
Mr.doob 已提交
579 580
				_movePrev.copy( _moveCurr );
				_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
M
r101  
Mr.doob 已提交
581

M
r128  
Mr.doob 已提交
582
			} else if ( state === STATE.ZOOM && ! scope.noZoom ) {
M
r101  
Mr.doob 已提交
583

M
r128  
Mr.doob 已提交
584
				_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
M
r101  
Mr.doob 已提交
585

M
r128  
Mr.doob 已提交
586
			} else if ( state === STATE.PAN && ! scope.noPan ) {
M
r101  
Mr.doob 已提交
587

M
r128  
Mr.doob 已提交
588
				_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
M
r101  
Mr.doob 已提交
589

M
r128  
Mr.doob 已提交
590
			}
M
r101  
Mr.doob 已提交
591 592 593

		}

M
r130  
Mr.doob 已提交
594
		function onMouseUp() {
M
r120.1  
Mr.doob 已提交
595

M
r128  
Mr.doob 已提交
596
			_state = STATE.NONE;
M
r101  
Mr.doob 已提交
597

M
r128  
Mr.doob 已提交
598 599
			scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
			scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
M
r101  
Mr.doob 已提交
600

M
r128  
Mr.doob 已提交
601
			scope.dispatchEvent( _endEvent );
M
r101  
Mr.doob 已提交
602

M
r128  
Mr.doob 已提交
603
		}
M
r120  
Mr.doob 已提交
604

M
r130  
Mr.doob 已提交
605
		function onMouseWheel( event ) {
M
r101  
Mr.doob 已提交
606

M
r128  
Mr.doob 已提交
607
			if ( scope.enabled === false ) return;
M
r101  
Mr.doob 已提交
608

M
r128  
Mr.doob 已提交
609
			if ( scope.noZoom === true ) return;
M
r101  
Mr.doob 已提交
610

M
r128  
Mr.doob 已提交
611
			event.preventDefault();
M
r101  
Mr.doob 已提交
612

M
r128  
Mr.doob 已提交
613
			switch ( event.deltaMode ) {
M
r101  
Mr.doob 已提交
614

M
r128  
Mr.doob 已提交
615 616 617 618
				case 2:
					// Zoom in pages
					_zoomStart.y -= event.deltaY * 0.025;
					break;
M
r101  
Mr.doob 已提交
619

M
r128  
Mr.doob 已提交
620 621 622 623 624 625 626 627 628
				case 1:
					// Zoom in lines
					_zoomStart.y -= event.deltaY * 0.01;
					break;

				default:
					// undefined, 0, assume pixels
					_zoomStart.y -= event.deltaY * 0.00025;
					break;
M
r101  
Mr.doob 已提交
629

M
r128  
Mr.doob 已提交
630
			}
M
r101  
Mr.doob 已提交
631

M
r128  
Mr.doob 已提交
632 633
			scope.dispatchEvent( _startEvent );
			scope.dispatchEvent( _endEvent );
M
r101  
Mr.doob 已提交
634 635 636

		}

M
r130  
Mr.doob 已提交
637
		function onTouchStart( event ) {
M
r101  
Mr.doob 已提交
638

M
r130  
Mr.doob 已提交
639
			trackPointer( event );
M
r101  
Mr.doob 已提交
640

M
r130  
Mr.doob 已提交
641
			switch ( _pointers.length ) {
M
r105  
Mr.doob 已提交
642

M
r128  
Mr.doob 已提交
643 644
				case 1:
					_state = STATE.TOUCH_ROTATE;
M
r130  
Mr.doob 已提交
645
					_moveCurr.copy( getMouseOnCircle( _pointers[ 0 ].pageX, _pointers[ 0 ].pageY ) );
M
r128  
Mr.doob 已提交
646 647
					_movePrev.copy( _moveCurr );
					break;
M
r101  
Mr.doob 已提交
648

M
r128  
Mr.doob 已提交
649 650
				default: // 2 or more
					_state = STATE.TOUCH_ZOOM_PAN;
M
r130  
Mr.doob 已提交
651 652
					const dx = _pointers[ 0 ].pageX - _pointers[ 1 ].pageX;
					const dy = _pointers[ 0 ].pageY - _pointers[ 1 ].pageY;
M
r128  
Mr.doob 已提交
653
					_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
M
r101  
Mr.doob 已提交
654

M
r130  
Mr.doob 已提交
655 656
					const x = ( _pointers[ 0 ].pageX + _pointers[ 1 ].pageX ) / 2;
					const y = ( _pointers[ 0 ].pageY + _pointers[ 1 ].pageY ) / 2;
M
r128  
Mr.doob 已提交
657 658 659
					_panStart.copy( getMouseOnScreen( x, y ) );
					_panEnd.copy( _panStart );
					break;
M
r101  
Mr.doob 已提交
660

M
r128  
Mr.doob 已提交
661
			}
M
r101  
Mr.doob 已提交
662

M
r128  
Mr.doob 已提交
663
			scope.dispatchEvent( _startEvent );
M
r101  
Mr.doob 已提交
664 665 666

		}

M
r130  
Mr.doob 已提交
667
		function onTouchMove( event ) {
M
r101  
Mr.doob 已提交
668

M
r130  
Mr.doob 已提交
669
			trackPointer( event );
M
r101  
Mr.doob 已提交
670

M
r130  
Mr.doob 已提交
671
			switch ( _pointers.length ) {
M
r101  
Mr.doob 已提交
672

M
r128  
Mr.doob 已提交
673 674
				case 1:
					_movePrev.copy( _moveCurr );
M
r130  
Mr.doob 已提交
675
					_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
M
r128  
Mr.doob 已提交
676
					break;
M
r101  
Mr.doob 已提交
677

M
r128  
Mr.doob 已提交
678
				default: // 2 or more
M
r130  
Mr.doob 已提交
679 680 681 682 683

					const position = getSecondPointerPosition( event );

					const dx = event.pageX - position.x;
					const dy = event.pageY - position.y;
M
r128  
Mr.doob 已提交
684
					_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
M
r101  
Mr.doob 已提交
685

M
r130  
Mr.doob 已提交
686 687
					const x = ( event.pageX + position.x ) / 2;
					const y = ( event.pageY + position.y ) / 2;
M
r128  
Mr.doob 已提交
688 689
					_panEnd.copy( getMouseOnScreen( x, y ) );
					break;
M
r101  
Mr.doob 已提交
690

M
r128  
Mr.doob 已提交
691
			}
M
r101  
Mr.doob 已提交
692 693 694

		}

M
r130  
Mr.doob 已提交
695
		function onTouchEnd( event ) {
M
r101  
Mr.doob 已提交
696

M
r130  
Mr.doob 已提交
697
			switch ( _pointers.length ) {
M
r101  
Mr.doob 已提交
698

M
r128  
Mr.doob 已提交
699 700 701
				case 0:
					_state = STATE.NONE;
					break;
M
r101  
Mr.doob 已提交
702

M
r128  
Mr.doob 已提交
703 704
				case 1:
					_state = STATE.TOUCH_ROTATE;
M
r130  
Mr.doob 已提交
705
					_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
M
r128  
Mr.doob 已提交
706 707
					_movePrev.copy( _moveCurr );
					break;
M
r101  
Mr.doob 已提交
708

M
r128  
Mr.doob 已提交
709
			}
M
r101  
Mr.doob 已提交
710

M
r128  
Mr.doob 已提交
711
			scope.dispatchEvent( _endEvent );
M
r101  
Mr.doob 已提交
712

M
r128  
Mr.doob 已提交
713
		}
M
r101  
Mr.doob 已提交
714

M
r128  
Mr.doob 已提交
715
		function contextmenu( event ) {
M
r101  
Mr.doob 已提交
716

M
r128  
Mr.doob 已提交
717
			if ( scope.enabled === false ) return;
M
r101  
Mr.doob 已提交
718

M
r128  
Mr.doob 已提交
719
			event.preventDefault();
M
r101  
Mr.doob 已提交
720

M
r128  
Mr.doob 已提交
721
		}
M
r101  
Mr.doob 已提交
722

M
r130  
Mr.doob 已提交
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
		function addPointer( event ) {

			_pointers.push( event );

		}

		function removePointer( event ) {

			delete _pointerPositions[ event.pointerId ];

			for ( let i = 0; i < _pointers.length; i ++ ) {

				if ( _pointers[ i ].pointerId == event.pointerId ) {

					_pointers.splice( i, 1 );
					return;

				}

			}

		}

		function trackPointer( event ) {

			let position = _pointerPositions[ event.pointerId ];

			if ( position === undefined ) {

				position = new Vector2();
				_pointerPositions[ event.pointerId ] = position;

			}

			position.set( event.pageX, event.pageY );

		}

		function getSecondPointerPosition( event ) {

			const pointer = ( event.pointerId === _pointers[ 0 ].pointerId ) ? _pointers[ 1 ] : _pointers[ 0 ];

			return _pointerPositions[ pointer.pointerId ];

		}

M
r128  
Mr.doob 已提交
769
		this.dispose = function () {
M
r101  
Mr.doob 已提交
770

M
r128  
Mr.doob 已提交
771
			scope.domElement.removeEventListener( 'contextmenu', contextmenu );
M
r120  
Mr.doob 已提交
772

M
r128  
Mr.doob 已提交
773
			scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
M
r130  
Mr.doob 已提交
774 775
			scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
			scope.domElement.removeEventListener( 'wheel', onMouseWheel );
M
r101  
Mr.doob 已提交
776

M
r128  
Mr.doob 已提交
777 778
			window.removeEventListener( 'keydown', keydown );
			window.removeEventListener( 'keyup', keyup );
M
r101  
Mr.doob 已提交
779

M
r128  
Mr.doob 已提交
780
		};
M
r101  
Mr.doob 已提交
781

M
r128  
Mr.doob 已提交
782
		this.domElement.addEventListener( 'contextmenu', contextmenu );
M
r120  
Mr.doob 已提交
783

M
r128  
Mr.doob 已提交
784
		this.domElement.addEventListener( 'pointerdown', onPointerDown );
M
r130  
Mr.doob 已提交
785 786
		this.domElement.addEventListener( 'pointercancel', onPointerCancel );
		this.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );
M
r101  
Mr.doob 已提交
787

M
r120  
Mr.doob 已提交
788

M
r128  
Mr.doob 已提交
789 790
		window.addEventListener( 'keydown', keydown );
		window.addEventListener( 'keyup', keyup );
M
r101  
Mr.doob 已提交
791

M
r128  
Mr.doob 已提交
792
		this.handleResize();
M
r101  
Mr.doob 已提交
793

M
r128  
Mr.doob 已提交
794 795
		// force an update at start
		this.update();
M
r101  
Mr.doob 已提交
796

M
r128  
Mr.doob 已提交
797
	}
M
r101  
Mr.doob 已提交
798

M
r128  
Mr.doob 已提交
799
}
M
r101  
Mr.doob 已提交
800 801

export { TrackballControls };