@@ -135,7 +135,7 @@ export class SmoothControls extends EventDispatcher {
135
135
// Pan state
136
136
public enablePan = true ;
137
137
private panProjection = new Matrix3 ( ) ;
138
- private panMetersPerPixel = 0 ;
138
+ private panPerPixel = 0 ;
139
139
140
140
// Internal orbital position state
141
141
private spherical = new Spherical ( ) ;
@@ -525,7 +525,7 @@ export class SmoothControls extends EventDispatcher {
525
525
}
526
526
527
527
private onMouseMove = ( event : MouseEvent ) => {
528
- if ( this . panMetersPerPixel > 0 ) {
528
+ if ( this . panPerPixel > 0 ) {
529
529
this . movePan ( event . clientX , event . clientY ) ;
530
530
} else {
531
531
this . handleSinglePointerMove ( event ) ;
@@ -560,7 +560,7 @@ export class SmoothControls extends EventDispatcher {
560
560
this . userAdjustOrbit ( 0 , 0 , deltaZoom ) ;
561
561
}
562
562
563
- if ( this . panMetersPerPixel > 0 ) {
563
+ if ( this . panPerPixel > 0 ) {
564
564
const thisX =
565
565
0.5 * ( targetTouches [ 0 ] . clientX + targetTouches [ 1 ] . clientX ) ;
566
566
const thisY =
@@ -612,10 +612,10 @@ export class SmoothControls extends EventDispatcher {
612
612
613
613
private initializePan ( ) {
614
614
( this . scene . element as any ) [ $panElement ] . style . opacity = 1 ;
615
- const { theta, phi, radius } = this . spherical ;
615
+ const { theta, phi} = this . spherical ;
616
616
const psi = theta - this . scene . yaw ;
617
- this . panMetersPerPixel = ( PAN_SENSITIVITY * radius ) /
618
- this . element . getBoundingClientRect ( ) . height ;
617
+ this . panPerPixel =
618
+ PAN_SENSITIVITY / this . element . getBoundingClientRect ( ) . height ;
619
619
this . panProjection . set (
620
620
- Math . cos ( psi ) ,
621
621
- Math . cos ( phi ) * Math . sin ( psi ) ,
@@ -634,7 +634,8 @@ export class SmoothControls extends EventDispatcher {
634
634
thisX - lastPointerPosition . clientX ,
635
635
thisY - lastPointerPosition . clientY ,
636
636
0 ) ;
637
- dxy . multiplyScalar ( this . panMetersPerPixel ) ;
637
+ const metersPerPixel = this . spherical . radius * this . panPerPixel ;
638
+ dxy . multiplyScalar ( metersPerPixel ) ;
638
639
639
640
lastPointerPosition . clientX = thisX ;
640
641
lastPointerPosition . clientY = thisY ;
@@ -646,57 +647,65 @@ export class SmoothControls extends EventDispatcher {
646
647
}
647
648
648
649
private recenter ( pointer : Pointer ) {
649
- if ( ! this . enablePan ) {
650
+ if ( ! this . enablePan ||
651
+ Math . abs ( pointer . clientX - this . startPointerPosition . clientX ) >
652
+ TAP_DISTANCE ||
653
+ Math . abs ( pointer . clientY - this . startPointerPosition . clientY ) >
654
+ TAP_DISTANCE ) {
650
655
return ;
651
656
}
652
657
const { scene} = this ;
653
658
( scene . element as any ) [ $panElement ] . style . opacity = 0 ;
654
- if ( Math . abs ( pointer . clientX - this . startPointerPosition . clientX ) <
655
- TAP_DISTANCE &&
656
- Math . abs ( pointer . clientY - this . startPointerPosition . clientY ) <
657
- TAP_DISTANCE ) {
658
- const hit = scene . positionAndNormalFromPoint (
659
- scene . getNDC ( pointer . clientX , pointer . clientY ) ) ;
660
-
661
- if ( hit == null ) {
662
- const { cameraTarget} = scene . element ;
663
- scene . element . cameraTarget = '' ;
664
- scene . element . cameraTarget = cameraTarget ;
665
- // Zoom all the way out.
666
- this . userAdjustOrbit ( 0 , 0 , 1 ) ;
667
- } else {
668
- scene . target . worldToLocal ( hit . position ) ;
669
- scene . setTarget ( hit . position . x , hit . position . y , hit . position . z ) ;
670
- // Zoom in on the tapped point.
671
- this . userAdjustOrbit ( 0 , 0 , - 5 * ZOOM_SENSITIVITY ) ;
672
- }
673
- } else if ( this . panMetersPerPixel > 0 ) {
674
- const hit = scene . positionAndNormalFromPoint ( vector2 . set ( 0 , 0 ) ) ;
675
- if ( hit == null )
676
- return ;
677
659
660
+ const hit = scene . positionAndNormalFromPoint (
661
+ scene . getNDC ( pointer . clientX , pointer . clientY ) ) ;
662
+
663
+ if ( hit == null ) {
664
+ const { cameraTarget} = scene . element ;
665
+ scene . element . cameraTarget = '' ;
666
+ scene . element . cameraTarget = cameraTarget ;
667
+ // Zoom all the way out.
668
+ this . userAdjustOrbit ( 0 , 0 , 1 ) ;
669
+ } else {
678
670
scene . target . worldToLocal ( hit . position ) ;
679
- const goalTarget = scene . getTarget ( ) ;
680
- const { theta, phi} = this . spherical ;
681
-
682
- // Set target to surface hit point, except the target is still settling,
683
- // so offset the goal accordingly so the transition is smooth even though
684
- // this will drift the target slightly away from the hit point.
685
- const psi = theta - scene . yaw ;
686
- const n = vector3 . set (
687
- Math . sin ( phi ) * Math . sin ( psi ) ,
688
- Math . cos ( phi ) ,
689
- Math . sin ( phi ) * Math . cos ( psi ) ) ;
690
- const dr = n . dot ( hit . position . sub ( goalTarget ) ) ;
691
- goalTarget . add ( n . multiplyScalar ( dr ) ) ;
692
-
693
- scene . setTarget ( goalTarget . x , goalTarget . y , goalTarget . z ) ;
694
- // Change the camera radius to match the change in target so that the
695
- // camera itself does not move, unless it hits a radius bound.
696
- this . setOrbit ( undefined , undefined , this . goalSpherical . radius - dr ) ;
671
+ scene . setTarget ( hit . position . x , hit . position . y , hit . position . z ) ;
672
+ // Zoom in on the tapped point.
673
+ this . userAdjustOrbit ( 0 , 0 , - 5 * ZOOM_SENSITIVITY ) ;
697
674
}
698
675
}
699
676
677
+ private resetRadius ( ) {
678
+ if ( ! this . enablePan || this . panPerPixel === 0 ) {
679
+ return ;
680
+ }
681
+ const { scene} = this ;
682
+ ( scene . element as any ) [ $panElement ] . style . opacity = 0 ;
683
+
684
+ const hit = scene . positionAndNormalFromPoint ( vector2 . set ( 0 , 0 ) ) ;
685
+ if ( hit == null )
686
+ return ;
687
+
688
+ scene . target . worldToLocal ( hit . position ) ;
689
+ const goalTarget = scene . getTarget ( ) ;
690
+ const { theta, phi} = this . spherical ;
691
+
692
+ // Set target to surface hit point, except the target is still settling,
693
+ // so offset the goal accordingly so the transition is smooth even though
694
+ // this will drift the target slightly away from the hit point.
695
+ const psi = theta - scene . yaw ;
696
+ const n = vector3 . set (
697
+ Math . sin ( phi ) * Math . sin ( psi ) ,
698
+ Math . cos ( phi ) ,
699
+ Math . sin ( phi ) * Math . cos ( psi ) ) ;
700
+ const dr = n . dot ( hit . position . sub ( goalTarget ) ) ;
701
+ goalTarget . add ( n . multiplyScalar ( dr ) ) ;
702
+
703
+ scene . setTarget ( goalTarget . x , goalTarget . y , goalTarget . z ) ;
704
+ // Change the camera radius to match the change in target so that the
705
+ // camera itself does not move, unless it hits a radius bound.
706
+ this . setOrbit ( undefined , undefined , this . goalSpherical . radius - dr ) ;
707
+ }
708
+
700
709
private onPointerDown ( fn : ( ) => void ) {
701
710
if ( ! this . canInteract ) {
702
711
return ;
@@ -716,7 +725,11 @@ export class SmoothControls extends EventDispatcher {
716
725
event . shiftKey ) ) {
717
726
this . initializePan ( ) ;
718
727
}
719
- this . handleSinglePointerDown ( event ) ;
728
+ this . lastPointerPosition . clientX = event . clientX ;
729
+ this . lastPointerPosition . clientY = event . clientY ;
730
+ this . startPointerPosition . clientX = event . clientX ;
731
+ this . startPointerPosition . clientY = event . clientY ;
732
+ this . element . style . cursor = 'grabbing' ;
720
733
} ) ;
721
734
} ;
722
735
@@ -735,13 +748,21 @@ export class SmoothControls extends EventDispatcher {
735
748
} ;
736
749
737
750
private onTouchChange ( event : TouchEvent ) {
738
- const { targetTouches} = event ;
751
+ const { targetTouches, changedTouches } = event ;
739
752
740
753
switch ( targetTouches . length ) {
741
754
default :
742
755
case 1 :
743
756
this . touchMode = this . touchModeRotate ;
744
- this . handleSinglePointerDown ( targetTouches [ 0 ] ) ;
757
+ this . lastPointerPosition . clientX = targetTouches [ 0 ] . clientX ;
758
+ this . lastPointerPosition . clientY = targetTouches [ 0 ] . clientY ;
759
+ if ( targetTouches [ 0 ] . identifier ===
760
+ changedTouches [ 0 ] . identifier ) { // finger down
761
+ this . startPointerPosition . clientX = targetTouches [ 0 ] . clientX ;
762
+ this . startPointerPosition . clientY = targetTouches [ 0 ] . clientY ;
763
+ } else { // finger up
764
+ this . resetRadius ( ) ;
765
+ }
745
766
break ;
746
767
case 2 :
747
768
this . touchMode = ( this . touchDecided && this . touchMode === null ) ?
@@ -750,24 +771,22 @@ export class SmoothControls extends EventDispatcher {
750
771
this . touchDecided = true ;
751
772
if ( this . enablePan ) {
752
773
this . initializePan ( ) ;
774
+ const x = 0.5 * ( targetTouches [ 0 ] . clientX + targetTouches [ 1 ] . clientX ) ;
775
+ const y = 0.5 * ( targetTouches [ 0 ] . clientY + targetTouches [ 1 ] . clientY ) ;
776
+ this . lastPointerPosition . clientX = x ;
777
+ this . lastPointerPosition . clientY = y ;
778
+ this . startPointerPosition . clientX = x ;
779
+ this . startPointerPosition . clientY = y ;
753
780
}
754
781
break ;
755
782
}
756
783
757
784
this . lastTouches = targetTouches ;
758
785
}
759
786
760
- private handleSinglePointerDown ( pointer : Pointer ) {
761
- this . lastPointerPosition . clientX = pointer . clientX ;
762
- this . lastPointerPosition . clientY = pointer . clientY ;
763
- this . startPointerPosition . clientX = pointer . clientX ;
764
- this . startPointerPosition . clientY = pointer . clientY ;
765
- this . element . style . cursor = 'grabbing' ;
766
- }
767
-
768
787
private onPointerUp ( ) {
769
788
this . element . style . cursor = 'grab' ;
770
- this . panMetersPerPixel = 0 ;
789
+ this . panPerPixel = 0 ;
771
790
772
791
if ( this . isUserPointing ) {
773
792
this . dispatchEvent (
@@ -777,7 +796,11 @@ export class SmoothControls extends EventDispatcher {
777
796
778
797
private onMouseUp = ( event : MouseEvent ) => {
779
798
self . removeEventListener ( 'mousemove' , this . onMouseMove ) ;
780
- this . recenter ( event ) ;
799
+ if ( this . panPerPixel > 0 ) {
800
+ this . resetRadius ( ) ;
801
+ } else {
802
+ this . recenter ( event ) ;
803
+ }
781
804
782
805
this . onPointerUp ( ) ;
783
806
} ;
@@ -787,7 +810,11 @@ export class SmoothControls extends EventDispatcher {
787
810
this . onTouchChange ( event ) ;
788
811
}
789
812
if ( event . targetTouches . length === 0 ) {
790
- this . recenter ( event . changedTouches [ 0 ] ) ;
813
+ if ( this . panPerPixel > 0 ) {
814
+ this . resetRadius ( ) ;
815
+ } else {
816
+ this . recenter ( event . changedTouches [ 0 ] ) ;
817
+ }
791
818
}
792
819
793
820
this . onPointerUp ( ) ;
0 commit comments