TrackballControls.js 15.6 KB
Newer Older
1
/**
2
 * @author Eberhard Graether / http://egraether.com/
M
Mark Lundin 已提交
3
 * @author Mark Lundin 	/ http://mark-lundin.com
4 5
 * @author Simone Manini / http://daron1337.github.io
 * @author Luca Antiga 	/ http://lantiga.github.io
6 7
 */

8
THREE.TrackballControls = function ( object, domElement ) {
9

10 11 12
	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
Mr.doob 已提交
13
	var _this = this;
G
gero3 已提交
14
	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
15

16
	this.object = object;
17
	this.domElement = domElement;
18

19
	// API
20

21 22
	this.enabled = true;

23
	this.screen = { left: 0, top: 0, width: 0, height: 0 };
24

25 26 27
	this.rotateSpeed = 1.0;
	this.zoomSpeed = 1.2;
	this.panSpeed = 0.3;
28

29
	this.noRotate = false;
30 31
	this.noZoom = false;
	this.noPan = false;
32

33 34
	this.staticMoving = false;
	this.dynamicDampingFactor = 0.2;
35

36 37
	this.minDistance = 0;
	this.maxDistance = Infinity;
38

39
	this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
40

M
Mugen87 已提交
41
	this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.ZOOM, RIGHT: THREE.MOUSE.PAN };
42

43
	// internals
44

M
Mr.doob 已提交
45 46
	this.target = new THREE.Vector3();

47 48
	var EPS = 0.000001;

M
Mr.doob 已提交
49
	var lastPosition = new THREE.Vector3();
50
	var lastZoom = 1;
51

M
Mr.doob 已提交
52
	var _state = STATE.NONE,
M
Mugen87 已提交
53
		_keyState = STATE.NONE,
54

M
Mugen87 已提交
55
		_eye = new THREE.Vector3(),
56

M
Mugen87 已提交
57 58
		_movePrev = new THREE.Vector2(),
		_moveCurr = new THREE.Vector2(),
59

M
Mugen87 已提交
60 61
		_lastAxis = new THREE.Vector3(),
		_lastAngle = 0,
62

M
Mugen87 已提交
63 64
		_zoomStart = new THREE.Vector2(),
		_zoomEnd = new THREE.Vector2(),
65

M
Mugen87 已提交
66 67
		_touchZoomDistanceStart = 0,
		_touchZoomDistanceEnd = 0,
68

M
Mugen87 已提交
69 70
		_panStart = new THREE.Vector2(),
		_panEnd = new THREE.Vector2();
71

W
WestLangley 已提交
72 73 74 75 76
	// for reset

	this.target0 = this.target.clone();
	this.position0 = this.object.position.clone();
	this.up0 = this.object.up.clone();
77
	this.zoom0 = this.object.zoom;
W
WestLangley 已提交
78

M
Mr.doob 已提交
79 80 81
	// events

	var changeEvent = { type: 'change' };
G
gero3 已提交
82 83
	var startEvent = { type: 'start' };
	var endEvent = { type: 'end' };
M
Mr.doob 已提交
84

85

86
	// methods
87

88 89
	this.handleResize = function () {

90 91 92 93 94 95 96
		var box = this.domElement.getBoundingClientRect();
		// adjustments come from similar code in the jquery offset() function
		var d = this.domElement.ownerDocument.documentElement;
		this.screen.left = box.left + window.pageXOffset - d.clientLeft;
		this.screen.top = box.top + window.pageYOffset - d.clientTop;
		this.screen.width = box.width;
		this.screen.height = box.height;
97

98 99
	};

M
Mr.doob 已提交
100
	var getMouseOnScreen = ( function () {
101

102
		var vector = new THREE.Vector2();
103

104
		return function getMouseOnScreen( pageX, pageY ) {
M
Mr.doob 已提交
105 106 107 108 109 110 111

			vector.set(
				( pageX - _this.screen.left ) / _this.screen.width,
				( pageY - _this.screen.top ) / _this.screen.height
			);

			return vector;
112

M
Mr.doob 已提交
113
		};
114

M
Mr.doob 已提交
115
	}() );
116

117 118 119 120
	var getMouseOnCircle = ( function () {

		var vector = new THREE.Vector2();

121
		return function getMouseOnCircle( pageX, pageY ) {
122 123 124

			vector.set(
				( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
125
				( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
126 127 128
			);

			return vector;
G
gero3 已提交
129

130 131 132 133
		};

	}() );

M
Mugen87 已提交
134
	this.rotateCamera = ( function () {
135

136
		var axis = new THREE.Vector3(),
137 138 139 140 141 142
			quaternion = new THREE.Quaternion(),
			eyeDirection = new THREE.Vector3(),
			objectUpDirection = new THREE.Vector3(),
			objectSidewaysDirection = new THREE.Vector3(),
			moveDirection = new THREE.Vector3(),
			angle;
143

144
		return function rotateCamera() {
145

146 147
			moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
			angle = moveDirection.length();
148

149
			if ( angle ) {
150

151
				_eye.copy( _this.object.position ).sub( _this.target );
152

153 154 155
				eyeDirection.copy( _eye ).normalize();
				objectUpDirection.copy( _this.object.up ).normalize();
				objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
156

157 158
				objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
				objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
159

160
				moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
161

162
				axis.crossVectors( moveDirection, _eye ).normalize();
163

164 165
				angle *= _this.rotateSpeed;
				quaternion.setFromAxisAngle( axis, angle );
166

167 168
				_eye.applyQuaternion( quaternion );
				_this.object.up.applyQuaternion( quaternion );
169

170 171
				_lastAxis.copy( axis );
				_lastAngle = angle;
172

G
gero3 已提交
173
			} else if ( ! _this.staticMoving && _lastAngle ) {
174

175 176 177 178 179
				_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
				_eye.copy( _this.object.position ).sub( _this.target );
				quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
				_eye.applyQuaternion( quaternion );
				_this.object.up.applyQuaternion( quaternion );
180

181
			}
182

183 184
			_movePrev.copy( _moveCurr );

185
		};
186

G
gero3 已提交
187
	}() );
188

189

M
Mr.doob 已提交
190
	this.zoomCamera = function () {
191

192 193
		var factor;

M
Mr.doob 已提交
194
		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
195

196
			factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
197
			_touchZoomDistanceStart = _touchZoomDistanceEnd;
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

			if ( _this.object.isPerspectiveCamera ) {

				_eye.multiplyScalar( factor );

			} else if ( _this.object.isOrthographicCamera ) {

				_this.object.zoom *= factor;
				_this.object.updateProjectionMatrix();

			} else {

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

			}
213

214
		} else {
215

216
			factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
217

218
			if ( factor !== 1.0 && factor > 0.0 ) {
219

220 221 222 223 224 225 226 227 228 229 230 231 232 233
				if ( _this.object.isPerspectiveCamera ) {

					_eye.multiplyScalar( factor );

				} else if ( _this.object.isOrthographicCamera ) {

					_this.object.zoom /= factor;
					_this.object.updateProjectionMatrix();

				} else {

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

				}
234

235
			}
236

237
			if ( _this.staticMoving ) {
238

239
				_zoomStart.copy( _zoomEnd );
240

241
			} else {
242

243
				_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
244 245

			}
246 247 248

		}

249
	};
250

M
Mugen87 已提交
251
	this.panCamera = ( function () {
252

253 254 255
		var mouseChange = new THREE.Vector2(),
			objectUp = new THREE.Vector3(),
			pan = new THREE.Vector3();
256

257
		return function panCamera() {
258

259
			mouseChange.copy( _panEnd ).sub( _panStart );
260

261
			if ( mouseChange.lengthSq() ) {
262

263 264 265 266 267 268 269 270 271 272
				if ( _this.object.isOrthographicCamera ) {

					var scale_x = ( _this.object.right - _this.object.left ) / _this.object.zoom / _this.domElement.clientWidth;
					var scale_y = ( _this.object.top - _this.object.bottom ) / _this.object.zoom / _this.domElement.clientWidth;

					mouseChange.x *= scale_x;
					mouseChange.y *= scale_y;

				}

273
				mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
274

275 276
				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
277

278 279
				_this.object.position.add( pan );
				_this.target.add( pan );
280

281
				if ( _this.staticMoving ) {
282

283
					_panStart.copy( _panEnd );
284

285 286 287
				} else {

					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
288

289 290 291
				}

			}
G
gero3 已提交
292

293
		};
294

G
gero3 已提交
295
	}() );
296

M
Mr.doob 已提交
297
	this.checkDistances = function () {
298

G
gero3 已提交
299
		if ( ! _this.noZoom || ! _this.noPan ) {
300

301
			if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
302

303
				_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
M
michaelg 已提交
304
				_zoomStart.copy( _zoomEnd );
305 306 307

			}

308
			if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
309

310
				_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
M
michaelg 已提交
311
				_zoomStart.copy( _zoomEnd );
312 313

			}
314 315 316

		}

317 318
	};

M
Mr.doob 已提交
319
	this.update = function () {
M
Mr.doob 已提交
320

321
		_eye.subVectors( _this.object.position, _this.target );
M
Mr.doob 已提交
322

G
gero3 已提交
323
		if ( ! _this.noRotate ) {
M
Mr.doob 已提交
324 325 326 327

			_this.rotateCamera();

		}
328

G
gero3 已提交
329
		if ( ! _this.noZoom ) {
M
Mr.doob 已提交
330 331 332 333 334

			_this.zoomCamera();

		}

G
gero3 已提交
335
		if ( ! _this.noPan ) {
M
Mr.doob 已提交
336 337 338 339 340

			_this.panCamera();

		}

341
		_this.object.position.addVectors( _this.target, _eye );
M
Mr.doob 已提交
342

343
		if ( _this.object.isPerspectiveCamera ) {
M
Mr.doob 已提交
344

345
			_this.checkDistances();
M
Mr.doob 已提交
346

347 348 349 350 351 352 353 354 355
			_this.object.lookAt( _this.target );

			if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {

				_this.dispatchEvent( changeEvent );

				lastPosition.copy( _this.object.position );

			}
356

357
		} else if ( _this.object.isOrthographicCamera ) {
M
Mr.doob 已提交
358

359 360
			_this.object.lookAt( _this.target );

M
Mugen87 已提交
361
			if ( lastPosition.distanceToSquared( _this.object.position ) > EPS || lastZoom !== _this.object.zoom ) {
362 363 364 365 366 367 368 369 370 371 372

				_this.dispatchEvent( changeEvent );

				lastPosition.copy( _this.object.position );
				lastZoom = _this.object.zoom;

			}

		} else {

			console.warn( 'THREE.TrackballControls: Unsupported camera type' );
M
Mr.doob 已提交
373 374 375 376 377

		}

	};

W
WestLangley 已提交
378 379 380
	this.reset = function () {

		_state = STATE.NONE;
M
Mugen87 已提交
381
		_keyState = STATE.NONE;
W
WestLangley 已提交
382 383 384 385

		_this.target.copy( _this.target0 );
		_this.object.position.copy( _this.position0 );
		_this.object.up.copy( _this.up0 );
386 387 388
		_this.object.zoom = _this.zoom0;

		_this.object.updateProjectionMatrix();
W
WestLangley 已提交
389 390 391 392 393

		_eye.subVectors( _this.object.position, _this.target );

		_this.object.lookAt( _this.target );

394
		_this.dispatchEvent( changeEvent );
W
WestLangley 已提交
395 396

		lastPosition.copy( _this.object.position );
397
		lastZoom = _this.object.zoom;
W
WestLangley 已提交
398 399 400

	};

401
	// listeners
402

403
	function keydown( event ) {
404

405
		if ( _this.enabled === false ) return;
406

407
		window.removeEventListener( 'keydown', keydown );
408

M
Mugen87 已提交
409
		if ( _keyState !== STATE.NONE ) {
410

411
			return;
412

G
gero3 已提交
413
		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
414

M
Mugen87 已提交
415
			_keyState = STATE.ROTATE;
416

G
gero3 已提交
417
		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
418

M
Mugen87 已提交
419
			_keyState = STATE.ZOOM;
420

G
gero3 已提交
421
		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
422

M
Mugen87 已提交
423
			_keyState = STATE.PAN;
424 425

		}
426

M
Mr.doob 已提交
427
	}
428

M
Mugen87 已提交
429
	function keyup() {
430

431
		if ( _this.enabled === false ) return;
432

M
Mugen87 已提交
433
		_keyState = STATE.NONE;
434

435
		window.addEventListener( 'keydown', keydown, false );
436

M
Mr.doob 已提交
437
	}
438

439
	function mousedown( event ) {
440

441
		if ( _this.enabled === false ) return;
442

443 444 445
		event.preventDefault();
		event.stopPropagation();

446
		if ( _state === STATE.NONE ) {
447

448 449
			switch ( event.button ) {

M
Mugen87 已提交
450
				case _this.mouseButtons.LEFT:
451 452 453
					_state = STATE.ROTATE;
					break;

M
Mugen87 已提交
454
				case _this.mouseButtons.MIDDLE:
455 456 457
					_state = STATE.ZOOM;
					break;

M
Mugen87 已提交
458
				case _this.mouseButtons.RIGHT:
459 460 461 462 463 464 465
					_state = STATE.PAN;
					break;

				default:
					_state = STATE.NONE;

			}
466

M
Mr.doob 已提交
467
		}
468

M
Mugen87 已提交
469 470 471
		var state = ( _keyState !== STATE.NONE ) ? _keyState : _state;

		if ( state === STATE.ROTATE && ! _this.noRotate ) {
472

473
			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
G
gero3 已提交
474
			_movePrev.copy( _moveCurr );
475

M
Mugen87 已提交
476
		} else if ( state === STATE.ZOOM && ! _this.noZoom ) {
477

M
Mr.doob 已提交
478
			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
G
gero3 已提交
479
			_zoomEnd.copy( _zoomStart );
480

M
Mugen87 已提交
481
		} else if ( state === STATE.PAN && ! _this.noPan ) {
482

M
Mr.doob 已提交
483
			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
G
gero3 已提交
484
			_panEnd.copy( _panStart );
485

486
		}
M
Mr.doob 已提交
487

M
Mr.doob 已提交
488 489
		document.addEventListener( 'mousemove', mousemove, false );
		document.addEventListener( 'mouseup', mouseup, false );
490

M
Mr.doob 已提交
491
		_this.dispatchEvent( startEvent );
492

M
Mr.doob 已提交
493
	}
494

495
	function mousemove( event ) {
496

497 498
		if ( _this.enabled === false ) return;

499 500 501
		event.preventDefault();
		event.stopPropagation();

M
Mugen87 已提交
502 503 504
		var state = ( _keyState !== STATE.NONE ) ? _keyState : _state;

		if ( state === STATE.ROTATE && ! _this.noRotate ) {
505

G
gero3 已提交
506
			_movePrev.copy( _moveCurr );
507
			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
508

M
Mugen87 已提交
509
		} else if ( state === STATE.ZOOM && ! _this.noZoom ) {
510

M
Mr.doob 已提交
511
			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
512

M
Mugen87 已提交
513
		} else if ( state === STATE.PAN && ! _this.noPan ) {
514

M
Mr.doob 已提交
515
			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
516

517
		}
518

M
Mr.doob 已提交
519
	}
520

521
	function mouseup( event ) {
522

523
		if ( _this.enabled === false ) return;
524

525 526 527
		event.preventDefault();
		event.stopPropagation();

528
		_state = STATE.NONE;
529

M
Mr.doob 已提交
530 531
		document.removeEventListener( 'mousemove', mousemove );
		document.removeEventListener( 'mouseup', mouseup );
532
		_this.dispatchEvent( endEvent );
533

M
Mr.doob 已提交
534
	}
535

536 537
	function mousewheel( event ) {

538
		if ( _this.enabled === false ) return;
M
Mugen87 已提交
539

A
ADRG1T 已提交
540
		if ( _this.noZoom === true ) return;
541

542 543 544
		event.preventDefault();
		event.stopPropagation();

545 546
		switch ( event.deltaMode ) {

547 548 549 550
			case 2:
				// Zoom in pages
				_zoomStart.y -= event.deltaY * 0.025;
				break;
F
Fred Ludlow 已提交
551

552
			case 1:
553
				// Zoom in lines
554 555 556 557
				_zoomStart.y -= event.deltaY * 0.01;
				break;

			default:
F
Fred Ludlow 已提交
558
				// undefined, 0, assume pixels
559 560
				_zoomStart.y -= event.deltaY * 0.00025;
				break;
F
Fred Ludlow 已提交
561

562
		}
563

564 565
		_this.dispatchEvent( startEvent );
		_this.dispatchEvent( endEvent );
566 567 568

	}

M
Mr.doob 已提交
569 570
	function touchstart( event ) {

571
		if ( _this.enabled === false ) return;
M
Mugen87 已提交
572

573
		event.preventDefault();
M
Mr.doob 已提交
574 575 576 577

		switch ( event.touches.length ) {

			case 1:
578
				_state = STATE.TOUCH_ROTATE;
579
				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
G
gero3 已提交
580
				_movePrev.copy( _moveCurr );
M
Mr.doob 已提交
581
				break;
582

583
			default: // 2 or more
M
Mr.doob 已提交
584
				_state = STATE.TOUCH_ZOOM_PAN;
585 586 587
				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
M
Mr.doob 已提交
588 589 590

				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
591
				_panStart.copy( getMouseOnScreen( x, y ) );
M
Mr.doob 已提交
592
				_panEnd.copy( _panStart );
M
Mr.doob 已提交
593 594 595
				break;

		}
596

597
		_this.dispatchEvent( startEvent );
M
Mr.doob 已提交
598 599 600 601 602

	}

	function touchmove( event ) {

603
		if ( _this.enabled === false ) return;
M
Mr.doob 已提交
604

605 606 607
		event.preventDefault();
		event.stopPropagation();

M
Mr.doob 已提交
608 609 610
		switch ( event.touches.length ) {

			case 1:
G
gero3 已提交
611
				_movePrev.copy( _moveCurr );
S
Shaw 已提交
612
				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
M
Mr.doob 已提交
613
				break;
614

615
			default: // 2 or more
616 617
				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
618
				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
M
Mr.doob 已提交
619 620 621 622

				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
				_panEnd.copy( getMouseOnScreen( x, y ) );
M
Mr.doob 已提交
623 624
				break;

625 626 627 628 629 630 631 632 633 634
		}

	}

	function touchend( event ) {

		if ( _this.enabled === false ) return;

		switch ( event.touches.length ) {

S
Shaw 已提交
635 636 637 638
			case 0:
				_state = STATE.NONE;
				break;

639
			case 1:
640
				_state = STATE.TOUCH_ROTATE;
S
Shaw 已提交
641 642
				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
				_movePrev.copy( _moveCurr );
643 644
				break;

M
Mr.doob 已提交
645 646
		}

647
		_this.dispatchEvent( endEvent );
648

M
Mr.doob 已提交
649 650
	}

D
dubejf 已提交
651
	function contextmenu( event ) {
G
gero3 已提交
652

653 654
		if ( _this.enabled === false ) return;

G
gero3 已提交
655 656
		event.preventDefault();

D
dubejf 已提交
657
	}
658

M
Mugen87 已提交
659
	this.dispose = function () {
D
dubejf 已提交
660 661 662

		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
		this.domElement.removeEventListener( 'mousedown', mousedown, false );
M
Mr.doob 已提交
663
		this.domElement.removeEventListener( 'wheel', mousewheel, false );
D
dubejf 已提交
664 665 666 667 668 669 670

		this.domElement.removeEventListener( 'touchstart', touchstart, false );
		this.domElement.removeEventListener( 'touchend', touchend, false );
		this.domElement.removeEventListener( 'touchmove', touchmove, false );

		document.removeEventListener( 'mousemove', mousemove, false );
		document.removeEventListener( 'mouseup', mouseup, false );
M
Mr.doob 已提交
671

672 673
		window.removeEventListener( 'keydown', keydown, false );
		window.removeEventListener( 'keyup', keyup, false );
D
dubejf 已提交
674

M
Mr.doob 已提交
675
	};
D
dubejf 已提交
676 677 678

	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
	this.domElement.addEventListener( 'mousedown', mousedown, false );
M
Mr.doob 已提交
679
	this.domElement.addEventListener( 'wheel', mousewheel, false );
M
Mr.doob 已提交
680 681

	this.domElement.addEventListener( 'touchstart', touchstart, false );
682
	this.domElement.addEventListener( 'touchend', touchend, false );
M
Mr.doob 已提交
683
	this.domElement.addEventListener( 'touchmove', touchmove, false );
M
Mr.doob 已提交
684

685 686
	window.addEventListener( 'keydown', keydown, false );
	window.addEventListener( 'keyup', keyup, false );
687

688 689
	this.handleResize();

690 691 692
	// force an update at start
	this.update();

693
};
694

M
Mr.doob 已提交
695
THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
696
THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;