PageSourceSearch

https://www.theorchard.com/wp-content/themes/the-orchard/blocks/ho…?ver=b3ac0a65635bf8e174de92cda01920c9

js theorchard.com collected 2026-09-24 08:43:16 UTC 25,962 bytes, 1,085 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.