1 | ( function () {
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | const _changeEvent = {
|
10 | type: 'change'
|
11 | };
|
12 | const _startEvent = {
|
13 | type: 'start'
|
14 | };
|
15 | const _endEvent = {
|
16 | type: 'end'
|
17 | };
|
18 |
|
19 | class OrbitControls extends THREE.EventDispatcher {
|
20 |
|
21 | constructor( object, domElement ) {
|
22 |
|
23 | super();
|
24 | if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' );
|
25 | if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
|
26 | this.object = object;
|
27 | this.domElement = domElement;
|
28 | this.domElement.style.touchAction = 'none';
|
29 |
|
30 |
|
31 | this.enabled = true;
|
32 |
|
33 | this.target = new THREE.Vector3();
|
34 |
|
35 | this.minDistance = 0;
|
36 | this.maxDistance = Infinity;
|
37 |
|
38 | this.minZoom = 0;
|
39 | this.maxZoom = Infinity;
|
40 |
|
41 |
|
42 | this.minPolarAngle = 0;
|
43 |
|
44 | this.maxPolarAngle = Math.PI;
|
45 |
|
46 |
|
47 |
|
48 | this.minAzimuthAngle = - Infinity;
|
49 |
|
50 | this.maxAzimuthAngle = Infinity;
|
51 |
|
52 |
|
53 |
|
54 | this.enableDamping = false;
|
55 | this.dampingFactor = 0.05;
|
56 |
|
57 |
|
58 | this.enableZoom = true;
|
59 | this.zoomSpeed = 1.0;
|
60 |
|
61 | this.enableRotate = true;
|
62 | this.rotateSpeed = 1.0;
|
63 |
|
64 | this.enablePan = true;
|
65 | this.panSpeed = 1.0;
|
66 | this.screenSpacePanning = true;
|
67 |
|
68 | this.keyPanSpeed = 7.0;
|
69 |
|
70 |
|
71 |
|
72 | this.autoRotate = false;
|
73 | this.autoRotateSpeed = 2.0;
|
74 |
|
75 |
|
76 | this.keys = {
|
77 | LEFT: 'ArrowLeft',
|
78 | UP: 'ArrowUp',
|
79 | RIGHT: 'ArrowRight',
|
80 | BOTTOM: 'ArrowDown'
|
81 | };
|
82 |
|
83 | this.mouseButtons = {
|
84 | LEFT: THREE.MOUSE.ROTATE,
|
85 | MIDDLE: THREE.MOUSE.DOLLY,
|
86 | RIGHT: THREE.MOUSE.PAN
|
87 | };
|
88 |
|
89 | this.touches = {
|
90 | ONE: THREE.TOUCH.ROTATE,
|
91 | TWO: THREE.TOUCH.DOLLY_PAN
|
92 | };
|
93 |
|
94 | this.target0 = this.target.clone();
|
95 | this.position0 = this.object.position.clone();
|
96 | this.zoom0 = this.object.zoom;
|
97 |
|
98 | this._domElementKeyEvents = null;
|
99 |
|
100 |
|
101 |
|
102 | this.getPolarAngle = function () {
|
103 |
|
104 | return spherical.phi;
|
105 |
|
106 | };
|
107 |
|
108 | this.getAzimuthalAngle = function () {
|
109 |
|
110 | return spherical.theta;
|
111 |
|
112 | };
|
113 |
|
114 | this.getDistance = function () {
|
115 |
|
116 | return this.object.position.distanceTo( this.target );
|
117 |
|
118 | };
|
119 |
|
120 | this.listenToKeyEvents = function ( domElement ) {
|
121 |
|
122 | domElement.addEventListener( 'keydown', onKeyDown );
|
123 | this._domElementKeyEvents = domElement;
|
124 |
|
125 | };
|
126 |
|
127 | this.saveState = function () {
|
128 |
|
129 | scope.target0.copy( scope.target );
|
130 | scope.position0.copy( scope.object.position );
|
131 | scope.zoom0 = scope.object.zoom;
|
132 |
|
133 | };
|
134 |
|
135 | this.reset = function () {
|
136 |
|
137 | scope.target.copy( scope.target0 );
|
138 | scope.object.position.copy( scope.position0 );
|
139 | scope.object.zoom = scope.zoom0;
|
140 | scope.object.updateProjectionMatrix();
|
141 | scope.dispatchEvent( _changeEvent );
|
142 | scope.update();
|
143 | state = STATE.NONE;
|
144 |
|
145 | };
|
146 |
|
147 |
|
148 | this.update = function () {
|
149 |
|
150 | const offset = new THREE.Vector3();
|
151 |
|
152 | const quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
|
153 | const quatInverse = quat.clone().invert();
|
154 | const lastPosition = new THREE.Vector3();
|
155 | const lastQuaternion = new THREE.Quaternion();
|
156 | const twoPI = 2 * Math.PI;
|
157 | return function update() {
|
158 |
|
159 | const position = scope.object.position;
|
160 | offset.copy( position ).sub( scope.target );
|
161 |
|
162 | offset.applyQuaternion( quat );
|
163 |
|
164 | spherical.setFromVector3( offset );
|
165 |
|
166 | if ( scope.autoRotate && state === STATE.NONE ) {
|
167 |
|
168 | rotateLeft( getAutoRotationAngle() );
|
169 |
|
170 | }
|
171 |
|
172 | if ( scope.enableDamping ) {
|
173 |
|
174 | spherical.theta += sphericalDelta.theta * scope.dampingFactor;
|
175 | spherical.phi += sphericalDelta.phi * scope.dampingFactor;
|
176 |
|
177 | } else {
|
178 |
|
179 | spherical.theta += sphericalDelta.theta;
|
180 | spherical.phi += sphericalDelta.phi;
|
181 |
|
182 | }
|
183 |
|
184 |
|
185 | let min = scope.minAzimuthAngle;
|
186 | let max = scope.maxAzimuthAngle;
|
187 |
|
188 | if ( isFinite( min ) && isFinite( max ) ) {
|
189 |
|
190 | if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
|
191 | if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
|
192 |
|
193 | if ( min <= max ) {
|
194 |
|
195 | spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
|
196 |
|
197 | } else {
|
198 |
|
199 | spherical.theta = spherical.theta > ( min + max ) / 2 ? Math.max( min, spherical.theta ) : Math.min( max, spherical.theta );
|
200 |
|
201 | }
|
202 |
|
203 | }
|
204 |
|
205 |
|
206 | spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
|
207 | spherical.makeSafe();
|
208 | spherical.radius *= scale;
|
209 |
|
210 | spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
|
211 |
|
212 | if ( scope.enableDamping === true ) {
|
213 |
|
214 | scope.target.addScaledVector( panOffset, scope.dampingFactor );
|
215 |
|
216 | } else {
|
217 |
|
218 | scope.target.add( panOffset );
|
219 |
|
220 | }
|
221 |
|
222 | offset.setFromSpherical( spherical );
|
223 |
|
224 | offset.applyQuaternion( quatInverse );
|
225 | position.copy( scope.target ).add( offset );
|
226 | scope.object.lookAt( scope.target );
|
227 |
|
228 | if ( scope.enableDamping === true ) {
|
229 |
|
230 | sphericalDelta.theta *= 1 - scope.dampingFactor;
|
231 | sphericalDelta.phi *= 1 - scope.dampingFactor;
|
232 | panOffset.multiplyScalar( 1 - scope.dampingFactor );
|
233 |
|
234 | } else {
|
235 |
|
236 | sphericalDelta.set( 0, 0, 0 );
|
237 | panOffset.set( 0, 0, 0 );
|
238 |
|
239 | }
|
240 |
|
241 | scale = 1;
|
242 |
|
243 |
|
244 |
|
245 | if ( zoomChanged || lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
|
246 |
|
247 | scope.dispatchEvent( _changeEvent );
|
248 | lastPosition.copy( scope.object.position );
|
249 | lastQuaternion.copy( scope.object.quaternion );
|
250 | zoomChanged = false;
|
251 | return true;
|
252 |
|
253 | }
|
254 |
|
255 | return false;
|
256 |
|
257 | };
|
258 |
|
259 | }();
|
260 |
|
261 | this.dispose = function () {
|
262 |
|
263 | scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
|
264 | scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
|
265 | scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
|
266 | scope.domElement.removeEventListener( 'wheel', onMouseWheel );
|
267 | scope.domElement.removeEventListener( 'pointermove', onPointerMove );
|
268 | scope.domElement.removeEventListener( 'pointerup', onPointerUp );
|
269 |
|
270 | if ( scope._domElementKeyEvents !== null ) {
|
271 |
|
272 | scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
|
273 |
|
274 | }
|
275 |
|
276 | };
|
277 |
|
278 |
|
279 |
|
280 |
|
281 | const scope = this;
|
282 | const STATE = {
|
283 | NONE: - 1,
|
284 | ROTATE: 0,
|
285 | DOLLY: 1,
|
286 | PAN: 2,
|
287 | TOUCH_ROTATE: 3,
|
288 | TOUCH_PAN: 4,
|
289 | TOUCH_DOLLY_PAN: 5,
|
290 | TOUCH_DOLLY_ROTATE: 6
|
291 | };
|
292 | let state = STATE.NONE;
|
293 | const EPS = 0.000001;
|
294 |
|
295 | const spherical = new THREE.Spherical();
|
296 | const sphericalDelta = new THREE.Spherical();
|
297 | let scale = 1;
|
298 | const panOffset = new THREE.Vector3();
|
299 | let zoomChanged = false;
|
300 | const rotateStart = new THREE.Vector2();
|
301 | const rotateEnd = new THREE.Vector2();
|
302 | const rotateDelta = new THREE.Vector2();
|
303 | const panStart = new THREE.Vector2();
|
304 | const panEnd = new THREE.Vector2();
|
305 | const panDelta = new THREE.Vector2();
|
306 | const dollyStart = new THREE.Vector2();
|
307 | const dollyEnd = new THREE.Vector2();
|
308 | const dollyDelta = new THREE.Vector2();
|
309 | const pointers = [];
|
310 | const pointerPositions = {};
|
311 |
|
312 | function getAutoRotationAngle() {
|
313 |
|
314 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
|
315 |
|
316 | }
|
317 |
|
318 | function getZoomScale() {
|
319 |
|
320 | return Math.pow( 0.95, scope.zoomSpeed );
|
321 |
|
322 | }
|
323 |
|
324 | function rotateLeft( angle ) {
|
325 |
|
326 | sphericalDelta.theta -= angle;
|
327 |
|
328 | }
|
329 |
|
330 | function rotateUp( angle ) {
|
331 |
|
332 | sphericalDelta.phi -= angle;
|
333 |
|
334 | }
|
335 |
|
336 | const panLeft = function () {
|
337 |
|
338 | const v = new THREE.Vector3();
|
339 | return function panLeft( distance, objectMatrix ) {
|
340 |
|
341 | v.setFromMatrixColumn( objectMatrix, 0 );
|
342 |
|
343 | v.multiplyScalar( - distance );
|
344 | panOffset.add( v );
|
345 |
|
346 | };
|
347 |
|
348 | }();
|
349 |
|
350 | const panUp = function () {
|
351 |
|
352 | const v = new THREE.Vector3();
|
353 | return function panUp( distance, objectMatrix ) {
|
354 |
|
355 | if ( scope.screenSpacePanning === true ) {
|
356 |
|
357 | v.setFromMatrixColumn( objectMatrix, 1 );
|
358 |
|
359 | } else {
|
360 |
|
361 | v.setFromMatrixColumn( objectMatrix, 0 );
|
362 | v.crossVectors( scope.object.up, v );
|
363 |
|
364 | }
|
365 |
|
366 | v.multiplyScalar( distance );
|
367 | panOffset.add( v );
|
368 |
|
369 | };
|
370 |
|
371 | }();
|
372 |
|
373 |
|
374 | const pan = function () {
|
375 |
|
376 | const offset = new THREE.Vector3();
|
377 | return function pan( deltaX, deltaY ) {
|
378 |
|
379 | const element = scope.domElement;
|
380 |
|
381 | if ( scope.object.isPerspectiveCamera ) {
|
382 |
|
383 |
|
384 | const position = scope.object.position;
|
385 | offset.copy( position ).sub( scope.target );
|
386 | let targetDistance = offset.length();
|
387 |
|
388 | targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 );
|
389 |
|
390 | panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
|
391 | panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
|
392 |
|
393 | } else if ( scope.object.isOrthographicCamera ) {
|
394 |
|
395 |
|
396 | panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
|
397 | panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
|
398 |
|
399 | } else {
|
400 |
|
401 |
|
402 | console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
|
403 | scope.enablePan = false;
|
404 |
|
405 | }
|
406 |
|
407 | };
|
408 |
|
409 | }();
|
410 |
|
411 | function dollyOut( dollyScale ) {
|
412 |
|
413 | if ( scope.object.isPerspectiveCamera ) {
|
414 |
|
415 | scale /= dollyScale;
|
416 |
|
417 | } else if ( scope.object.isOrthographicCamera ) {
|
418 |
|
419 | scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
|
420 | scope.object.updateProjectionMatrix();
|
421 | zoomChanged = true;
|
422 |
|
423 | } else {
|
424 |
|
425 | console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
|
426 | scope.enableZoom = false;
|
427 |
|
428 | }
|
429 |
|
430 | }
|
431 |
|
432 | function dollyIn( dollyScale ) {
|
433 |
|
434 | if ( scope.object.isPerspectiveCamera ) {
|
435 |
|
436 | scale *= dollyScale;
|
437 |
|
438 | } else if ( scope.object.isOrthographicCamera ) {
|
439 |
|
440 | scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
|
441 | scope.object.updateProjectionMatrix();
|
442 | zoomChanged = true;
|
443 |
|
444 | } else {
|
445 |
|
446 | console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
|
447 | scope.enableZoom = false;
|
448 |
|
449 | }
|
450 |
|
451 | }
|
452 |
|
453 |
|
454 |
|
455 |
|
456 | function handleMouseDownRotate( event ) {
|
457 |
|
458 | rotateStart.set( event.clientX, event.clientY );
|
459 |
|
460 | }
|
461 |
|
462 | function handleMouseDownDolly( event ) {
|
463 |
|
464 | dollyStart.set( event.clientX, event.clientY );
|
465 |
|
466 | }
|
467 |
|
468 | function handleMouseDownPan( event ) {
|
469 |
|
470 | panStart.set( event.clientX, event.clientY );
|
471 |
|
472 | }
|
473 |
|
474 | function handleMouseMoveRotate( event ) {
|
475 |
|
476 | rotateEnd.set( event.clientX, event.clientY );
|
477 | rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
|
478 | const element = scope.domElement;
|
479 | rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight );
|
480 |
|
481 | rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
|
482 | rotateStart.copy( rotateEnd );
|
483 | scope.update();
|
484 |
|
485 | }
|
486 |
|
487 | function handleMouseMoveDolly( event ) {
|
488 |
|
489 | dollyEnd.set( event.clientX, event.clientY );
|
490 | dollyDelta.subVectors( dollyEnd, dollyStart );
|
491 |
|
492 | if ( dollyDelta.y > 0 ) {
|
493 |
|
494 | dollyOut( getZoomScale() );
|
495 |
|
496 | } else if ( dollyDelta.y < 0 ) {
|
497 |
|
498 | dollyIn( getZoomScale() );
|
499 |
|
500 | }
|
501 |
|
502 | dollyStart.copy( dollyEnd );
|
503 | scope.update();
|
504 |
|
505 | }
|
506 |
|
507 | function handleMouseMovePan( event ) {
|
508 |
|
509 | panEnd.set( event.clientX, event.clientY );
|
510 | panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
|
511 | pan( panDelta.x, panDelta.y );
|
512 | panStart.copy( panEnd );
|
513 | scope.update();
|
514 |
|
515 | }
|
516 |
|
517 | function handleMouseUp() {
|
518 | }
|
519 |
|
520 | function handleMouseWheel( event ) {
|
521 |
|
522 | if ( event.deltaY < 0 ) {
|
523 |
|
524 | dollyIn( getZoomScale() );
|
525 |
|
526 | } else if ( event.deltaY > 0 ) {
|
527 |
|
528 | dollyOut( getZoomScale() );
|
529 |
|
530 | }
|
531 |
|
532 | scope.update();
|
533 |
|
534 | }
|
535 |
|
536 | function handleKeyDown( event ) {
|
537 |
|
538 | let needsUpdate = false;
|
539 |
|
540 | switch ( event.code ) {
|
541 |
|
542 | case scope.keys.UP:
|
543 | pan( 0, scope.keyPanSpeed );
|
544 | needsUpdate = true;
|
545 | break;
|
546 |
|
547 | case scope.keys.BOTTOM:
|
548 | pan( 0, - scope.keyPanSpeed );
|
549 | needsUpdate = true;
|
550 | break;
|
551 |
|
552 | case scope.keys.LEFT:
|
553 | pan( scope.keyPanSpeed, 0 );
|
554 | needsUpdate = true;
|
555 | break;
|
556 |
|
557 | case scope.keys.RIGHT:
|
558 | pan( - scope.keyPanSpeed, 0 );
|
559 | needsUpdate = true;
|
560 | break;
|
561 |
|
562 | }
|
563 |
|
564 | if ( needsUpdate ) {
|
565 |
|
566 |
|
567 | event.preventDefault();
|
568 | scope.update();
|
569 |
|
570 | }
|
571 |
|
572 | }
|
573 |
|
574 | function handleTouchStartRotate() {
|
575 |
|
576 | if ( pointers.length === 1 ) {
|
577 |
|
578 | rotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
|
579 |
|
580 | } else {
|
581 |
|
582 | const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
|
583 | const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
|
584 | rotateStart.set( x, y );
|
585 |
|
586 | }
|
587 |
|
588 | }
|
589 |
|
590 | function handleTouchStartPan() {
|
591 |
|
592 | if ( pointers.length === 1 ) {
|
593 |
|
594 | panStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
|
595 |
|
596 | } else {
|
597 |
|
598 | const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
|
599 | const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
|
600 | panStart.set( x, y );
|
601 |
|
602 | }
|
603 |
|
604 | }
|
605 |
|
606 | function handleTouchStartDolly() {
|
607 |
|
608 | const dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX;
|
609 | const dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY;
|
610 | const distance = Math.sqrt( dx * dx + dy * dy );
|
611 | dollyStart.set( 0, distance );
|
612 |
|
613 | }
|
614 |
|
615 | function handleTouchStartDollyPan() {
|
616 |
|
617 | if ( scope.enableZoom ) handleTouchStartDolly();
|
618 | if ( scope.enablePan ) handleTouchStartPan();
|
619 |
|
620 | }
|
621 |
|
622 | function handleTouchStartDollyRotate() {
|
623 |
|
624 | if ( scope.enableZoom ) handleTouchStartDolly();
|
625 | if ( scope.enableRotate ) handleTouchStartRotate();
|
626 |
|
627 | }
|
628 |
|
629 | function handleTouchMoveRotate( event ) {
|
630 |
|
631 | if ( pointers.length == 1 ) {
|
632 |
|
633 | rotateEnd.set( event.pageX, event.pageY );
|
634 |
|
635 | } else {
|
636 |
|
637 | const position = getSecondPointerPosition( event );
|
638 | const x = 0.5 * ( event.pageX + position.x );
|
639 | const y = 0.5 * ( event.pageY + position.y );
|
640 | rotateEnd.set( x, y );
|
641 |
|
642 | }
|
643 |
|
644 | rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
|
645 | const element = scope.domElement;
|
646 | rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight );
|
647 |
|
648 | rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
|
649 | rotateStart.copy( rotateEnd );
|
650 |
|
651 | }
|
652 |
|
653 | function handleTouchMovePan( event ) {
|
654 |
|
655 | if ( pointers.length === 1 ) {
|
656 |
|
657 | panEnd.set( event.pageX, event.pageY );
|
658 |
|
659 | } else {
|
660 |
|
661 | const position = getSecondPointerPosition( event );
|
662 | const x = 0.5 * ( event.pageX + position.x );
|
663 | const y = 0.5 * ( event.pageY + position.y );
|
664 | panEnd.set( x, y );
|
665 |
|
666 | }
|
667 |
|
668 | panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
|
669 | pan( panDelta.x, panDelta.y );
|
670 | panStart.copy( panEnd );
|
671 |
|
672 | }
|
673 |
|
674 | function handleTouchMoveDolly( event ) {
|
675 |
|
676 | const position = getSecondPointerPosition( event );
|
677 | const dx = event.pageX - position.x;
|
678 | const dy = event.pageY - position.y;
|
679 | const distance = Math.sqrt( dx * dx + dy * dy );
|
680 | dollyEnd.set( 0, distance );
|
681 | dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
|
682 | dollyOut( dollyDelta.y );
|
683 | dollyStart.copy( dollyEnd );
|
684 |
|
685 | }
|
686 |
|
687 | function handleTouchMoveDollyPan( event ) {
|
688 |
|
689 | if ( scope.enableZoom ) handleTouchMoveDolly( event );
|
690 | if ( scope.enablePan ) handleTouchMovePan( event );
|
691 |
|
692 | }
|
693 |
|
694 | function handleTouchMoveDollyRotate( event ) {
|
695 |
|
696 | if ( scope.enableZoom ) handleTouchMoveDolly( event );
|
697 | if ( scope.enableRotate ) handleTouchMoveRotate( event );
|
698 |
|
699 | }
|
700 |
|
701 | function handleTouchEnd() {
|
702 | }
|
703 |
|
704 |
|
705 |
|
706 |
|
707 | function onPointerDown( event ) {
|
708 |
|
709 | if ( scope.enabled === false ) return;
|
710 |
|
711 | if ( pointers.length === 0 ) {
|
712 |
|
713 | scope.domElement.setPointerCapture( event.pointerId );
|
714 | scope.domElement.addEventListener( 'pointermove', onPointerMove );
|
715 | scope.domElement.addEventListener( 'pointerup', onPointerUp );
|
716 |
|
717 | }
|
718 |
|
719 |
|
720 | addPointer( event );
|
721 |
|
722 | if ( event.pointerType === 'touch' ) {
|
723 |
|
724 | onTouchStart( event );
|
725 |
|
726 | } else {
|
727 |
|
728 | onMouseDown( event );
|
729 |
|
730 | }
|
731 |
|
732 | }
|
733 |
|
734 | function onPointerMove( event ) {
|
735 |
|
736 | if ( scope.enabled === false ) return;
|
737 |
|
738 | if ( event.pointerType === 'touch' ) {
|
739 |
|
740 | onTouchMove( event );
|
741 |
|
742 | } else {
|
743 |
|
744 | onMouseMove( event );
|
745 |
|
746 | }
|
747 |
|
748 | }
|
749 |
|
750 | function onPointerUp( event ) {
|
751 |
|
752 | if ( scope.enabled === false ) return;
|
753 |
|
754 | if ( event.pointerType === 'touch' ) {
|
755 |
|
756 | onTouchEnd();
|
757 |
|
758 | } else {
|
759 |
|
760 | onMouseUp( event );
|
761 |
|
762 | }
|
763 |
|
764 | removePointer( event );
|
765 |
|
766 | if ( pointers.length === 0 ) {
|
767 |
|
768 | scope.domElement.releasePointerCapture( event.pointerId );
|
769 | scope.domElement.removeEventListener( 'pointermove', onPointerMove );
|
770 | scope.domElement.removeEventListener( 'pointerup', onPointerUp );
|
771 |
|
772 | }
|
773 |
|
774 | }
|
775 |
|
776 | function onPointerCancel( event ) {
|
777 |
|
778 | removePointer( event );
|
779 |
|
780 | }
|
781 |
|
782 | function onMouseDown( event ) {
|
783 |
|
784 | let mouseAction;
|
785 |
|
786 | switch ( event.button ) {
|
787 |
|
788 | case 0:
|
789 | mouseAction = scope.mouseButtons.LEFT;
|
790 | break;
|
791 |
|
792 | case 1:
|
793 | mouseAction = scope.mouseButtons.MIDDLE;
|
794 | break;
|
795 |
|
796 | case 2:
|
797 | mouseAction = scope.mouseButtons.RIGHT;
|
798 | break;
|
799 |
|
800 | default:
|
801 | mouseAction = - 1;
|
802 |
|
803 | }
|
804 |
|
805 | switch ( mouseAction ) {
|
806 |
|
807 | case THREE.MOUSE.DOLLY:
|
808 | if ( scope.enableZoom === false ) return;
|
809 | handleMouseDownDolly( event );
|
810 | state = STATE.DOLLY;
|
811 | break;
|
812 |
|
813 | case THREE.MOUSE.ROTATE:
|
814 | if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
|
815 |
|
816 | if ( scope.enablePan === false ) return;
|
817 | handleMouseDownPan( event );
|
818 | state = STATE.PAN;
|
819 |
|
820 | } else {
|
821 |
|
822 | if ( scope.enableRotate === false ) return;
|
823 | handleMouseDownRotate( event );
|
824 | state = STATE.ROTATE;
|
825 |
|
826 | }
|
827 |
|
828 | break;
|
829 |
|
830 | case THREE.MOUSE.PAN:
|
831 | if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
|
832 |
|
833 | if ( scope.enableRotate === false ) return;
|
834 | handleMouseDownRotate( event );
|
835 | state = STATE.ROTATE;
|
836 |
|
837 | } else {
|
838 |
|
839 | if ( scope.enablePan === false ) return;
|
840 | handleMouseDownPan( event );
|
841 | state = STATE.PAN;
|
842 |
|
843 | }
|
844 |
|
845 | break;
|
846 |
|
847 | default:
|
848 | state = STATE.NONE;
|
849 |
|
850 | }
|
851 |
|
852 | if ( state !== STATE.NONE ) {
|
853 |
|
854 | scope.dispatchEvent( _startEvent );
|
855 |
|
856 | }
|
857 |
|
858 | }
|
859 |
|
860 | function onMouseMove( event ) {
|
861 |
|
862 | if ( scope.enabled === false ) return;
|
863 |
|
864 | switch ( state ) {
|
865 |
|
866 | case STATE.ROTATE:
|
867 | if ( scope.enableRotate === false ) return;
|
868 | handleMouseMoveRotate( event );
|
869 | break;
|
870 |
|
871 | case STATE.DOLLY:
|
872 | if ( scope.enableZoom === false ) return;
|
873 | handleMouseMoveDolly( event );
|
874 | break;
|
875 |
|
876 | case STATE.PAN:
|
877 | if ( scope.enablePan === false ) return;
|
878 | handleMouseMovePan( event );
|
879 | break;
|
880 |
|
881 | }
|
882 |
|
883 | }
|
884 |
|
885 | function onMouseUp( event ) {
|
886 |
|
887 | handleMouseUp( event );
|
888 | scope.dispatchEvent( _endEvent );
|
889 | state = STATE.NONE;
|
890 |
|
891 | }
|
892 |
|
893 | function onMouseWheel( event ) {
|
894 |
|
895 | if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE ) return;
|
896 | event.preventDefault();
|
897 | scope.dispatchEvent( _startEvent );
|
898 | handleMouseWheel( event );
|
899 | scope.dispatchEvent( _endEvent );
|
900 |
|
901 | }
|
902 |
|
903 | function onKeyDown( event ) {
|
904 |
|
905 | if ( scope.enabled === false || scope.enablePan === false ) return;
|
906 | handleKeyDown( event );
|
907 |
|
908 | }
|
909 |
|
910 | function onTouchStart( event ) {
|
911 |
|
912 | trackPointer( event );
|
913 |
|
914 | switch ( pointers.length ) {
|
915 |
|
916 | case 1:
|
917 | switch ( scope.touches.ONE ) {
|
918 |
|
919 | case THREE.TOUCH.ROTATE:
|
920 | if ( scope.enableRotate === false ) return;
|
921 | handleTouchStartRotate();
|
922 | state = STATE.TOUCH_ROTATE;
|
923 | break;
|
924 |
|
925 | case THREE.TOUCH.PAN:
|
926 | if ( scope.enablePan === false ) return;
|
927 | handleTouchStartPan();
|
928 | state = STATE.TOUCH_PAN;
|
929 | break;
|
930 |
|
931 | default:
|
932 | state = STATE.NONE;
|
933 |
|
934 | }
|
935 |
|
936 | break;
|
937 |
|
938 | case 2:
|
939 | switch ( scope.touches.TWO ) {
|
940 |
|
941 | case THREE.TOUCH.DOLLY_PAN:
|
942 | if ( scope.enableZoom === false && scope.enablePan === false ) return;
|
943 | handleTouchStartDollyPan();
|
944 | state = STATE.TOUCH_DOLLY_PAN;
|
945 | break;
|
946 |
|
947 | case THREE.TOUCH.DOLLY_ROTATE:
|
948 | if ( scope.enableZoom === false && scope.enableRotate === false ) return;
|
949 | handleTouchStartDollyRotate();
|
950 | state = STATE.TOUCH_DOLLY_ROTATE;
|
951 | break;
|
952 |
|
953 | default:
|
954 | state = STATE.NONE;
|
955 |
|
956 | }
|
957 |
|
958 | break;
|
959 |
|
960 | default:
|
961 | state = STATE.NONE;
|
962 |
|
963 | }
|
964 |
|
965 | if ( state !== STATE.NONE ) {
|
966 |
|
967 | scope.dispatchEvent( _startEvent );
|
968 |
|
969 | }
|
970 |
|
971 | }
|
972 |
|
973 | function onTouchMove( event ) {
|
974 |
|
975 | trackPointer( event );
|
976 |
|
977 | switch ( state ) {
|
978 |
|
979 | case STATE.TOUCH_ROTATE:
|
980 | if ( scope.enableRotate === false ) return;
|
981 | handleTouchMoveRotate( event );
|
982 | scope.update();
|
983 | break;
|
984 |
|
985 | case STATE.TOUCH_PAN:
|
986 | if ( scope.enablePan === false ) return;
|
987 | handleTouchMovePan( event );
|
988 | scope.update();
|
989 | break;
|
990 |
|
991 | case STATE.TOUCH_DOLLY_PAN:
|
992 | if ( scope.enableZoom === false && scope.enablePan === false ) return;
|
993 | handleTouchMoveDollyPan( event );
|
994 | scope.update();
|
995 | break;
|
996 |
|
997 | case STATE.TOUCH_DOLLY_ROTATE:
|
998 | if ( scope.enableZoom === false && scope.enableRotate === false ) return;
|
999 | handleTouchMoveDollyRotate( event );
|
1000 | scope.update();
|
1001 | break;
|
1002 |
|
1003 | default:
|
1004 | state = STATE.NONE;
|
1005 |
|
1006 | }
|
1007 |
|
1008 | }
|
1009 |
|
1010 | function onTouchEnd( event ) {
|
1011 |
|
1012 | handleTouchEnd( event );
|
1013 | scope.dispatchEvent( _endEvent );
|
1014 | state = STATE.NONE;
|
1015 |
|
1016 | }
|
1017 |
|
1018 | function onContextMenu( event ) {
|
1019 |
|
1020 | if ( scope.enabled === false ) return;
|
1021 | event.preventDefault();
|
1022 |
|
1023 | }
|
1024 |
|
1025 | function addPointer( event ) {
|
1026 |
|
1027 | pointers.push( event );
|
1028 |
|
1029 | }
|
1030 |
|
1031 | function removePointer( event ) {
|
1032 |
|
1033 | delete pointerPositions[ event.pointerId ];
|
1034 |
|
1035 | for ( let i = 0; i < pointers.length; i ++ ) {
|
1036 |
|
1037 | if ( pointers[ i ].pointerId == event.pointerId ) {
|
1038 |
|
1039 | pointers.splice( i, 1 );
|
1040 | return;
|
1041 |
|
1042 | }
|
1043 |
|
1044 | }
|
1045 |
|
1046 | }
|
1047 |
|
1048 | function trackPointer( event ) {
|
1049 |
|
1050 | let position = pointerPositions[ event.pointerId ];
|
1051 |
|
1052 | if ( position === undefined ) {
|
1053 |
|
1054 | position = new THREE.Vector2();
|
1055 | pointerPositions[ event.pointerId ] = position;
|
1056 |
|
1057 | }
|
1058 |
|
1059 | position.set( event.pageX, event.pageY );
|
1060 |
|
1061 | }
|
1062 |
|
1063 | function getSecondPointerPosition( event ) {
|
1064 |
|
1065 | const pointer = event.pointerId === pointers[ 0 ].pointerId ? pointers[ 1 ] : pointers[ 0 ];
|
1066 | return pointerPositions[ pointer.pointerId ];
|
1067 |
|
1068 | }
|
1069 |
|
1070 |
|
1071 | scope.domElement.addEventListener( 'contextmenu', onContextMenu );
|
1072 | scope.domElement.addEventListener( 'pointerdown', onPointerDown );
|
1073 | scope.domElement.addEventListener( 'pointercancel', onPointerCancel );
|
1074 | scope.domElement.addEventListener( 'wheel', onMouseWheel, {
|
1075 | passive: false
|
1076 | } );
|
1077 |
|
1078 | this.update();
|
1079 |
|
1080 | }
|
1081 |
|
1082 | }
|
1083 |
|
1084 |
|
1085 |
|
1086 |
|
1087 |
|
1088 |
|
1089 |
|
1090 |
|
1091 | class MapControls extends OrbitControls {
|
1092 |
|
1093 | constructor( object, domElement ) {
|
1094 |
|
1095 | super( object, domElement );
|
1096 | this.screenSpacePanning = false;
|
1097 |
|
1098 | this.mouseButtons.LEFT = THREE.MOUSE.PAN;
|
1099 | this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;
|
1100 | this.touches.ONE = THREE.TOUCH.PAN;
|
1101 | this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;
|
1102 |
|
1103 | }
|
1104 |
|
1105 | }
|
1106 |
|
1107 | THREE.MapControls = MapControls;
|
1108 | THREE.OrbitControls = OrbitControls;
|
1109 |
|
1110 | } )();
|