@@ -4,24 +4,29 @@ import {
4
4
TOUCH ,
5
5
Vector3 ,
6
6
Spherical ,
7
+ Clock ,
7
8
} from 'three' ;
8
9
9
10
10
- const rotateSpeed = 0.005 ;
11
- const dollySpeed = 1.0003 ;
12
-
13
11
export class OrreryControls extends Controls {
14
- target ;
15
- offset ;
16
- state ;
17
- constructor ( object , domElement = null , target ) {
12
+ offset = new Spherical ( 1 , 1 , 0 ) ;
13
+ rotateSpeed = 0.005 ;
14
+ dollySpeed = 1.0003 ;
15
+ easingSpeed = 0.5 ;
16
+ easingFunction = ( t ) => {
17
+ return 1 - Math . pow ( 1 - t , 3 ) ;
18
+ } ;
19
+ // we don't allow panning, so that there's always an object which is the target
20
+ mouseButtons = { LEFT : MOUSE . ROTATE , MIDDLE : MOUSE . DOLLY , RIGHT : null } ;
21
+ touches = { ONE : TOUCH . ROTATE , TWO : null } ;
22
+ constructor ( object , domElement = null , target , params = { } ) {
18
23
super ( object , domElement ) ;
19
24
20
- this . target = target ;
21
- this . offset = new Spherical ( 1 , 1 , 0 ) ;
22
- // we don't allow panning, so that there's always an object which is the target
23
- this . mouseButtons = { LEFT : MOUSE . ROTATE , MIDDLE : MOUSE . DOLLY , RIGHT : null } ;
24
- this . touches = { ONE : TOUCH . ROTATE , TWO : null } ;
25
+ Object . assign ( this , params ) ;
26
+
27
+ this . _target = target ;
28
+ this . _oldPosition = new Vector3 ( ) ;
29
+ this . _clock = new Clock ( ) ;
25
30
26
31
this . _onMouseMove = onMouseMove . bind ( this ) ;
27
32
this . _onMouseWheel = onMouseWheel . bind ( this ) ;
@@ -54,23 +59,45 @@ export class OrreryControls extends Controls {
54
59
this . offset . radius ,
55
60
this . target . geometry . parameters . radius + this . object . near ,
56
61
) ;
57
- let cameraPosition = new Vector3 ( )
62
+
63
+ // hacky way of getting the camera to point in the right direction
64
+ // in theory it should be possible to directly set the camera's rotation to the inverse of
65
+ // the offset's orientation, but I couldn't figure out the right conversions
66
+ let invLerpFactor = 1 - this . easingFunction (
67
+ Math . min ( 1 , this . _clock . getElapsedTime ( ) / this . easingSpeed )
68
+ ) ;
69
+ let fromPosition = this . _oldPosition . clone ( ) ;
70
+ let toPosition = new Vector3 ( )
58
71
. setFromSpherical ( this . offset )
59
72
. add ( this . target . position ) ;
60
- this . object . position . copy ( cameraPosition ) ;
61
- this . object . lookAt ( this . target . position ) ;
73
+ let invDeltaPosition = fromPosition . clone ( ) . sub ( toPosition ) . multiplyScalar ( invLerpFactor ) ;
74
+ let tweenPosition = toPosition . clone ( ) . add ( invDeltaPosition ) ;
75
+ let lookPosition = this . target . position . clone ( ) . add ( invDeltaPosition ) ;
76
+
77
+ this . object . position . copy ( tweenPosition ) ;
78
+ this . object . lookAt ( lookPosition ) ;
79
+ }
80
+
81
+ set target ( target ) {
82
+ this . _oldPosition = this . object . position . clone ( ) ;
83
+ this . _target = target ;
84
+ this . _clock . start ( ) ;
85
+ }
86
+
87
+ get target ( ) {
88
+ return this . _target ;
62
89
}
63
90
}
64
91
65
92
function onMouseMove ( event ) {
66
93
if ( event . buttons & 1 ) {
67
- this . offset . phi -= event . movementY * rotateSpeed ;
68
- this . offset . theta -= event . movementX * rotateSpeed ;
94
+ this . offset . phi -= event . movementY * this . rotateSpeed ;
95
+ this . offset . theta -= event . movementX * this . rotateSpeed ;
69
96
this . offset . makeSafe ( ) ;
70
97
}
71
98
}
72
99
73
100
function onMouseWheel ( event ) {
74
101
event . preventDefault ( ) ;
75
- this . offset . radius *= Math . pow ( dollySpeed , event . deltaY ) ;
102
+ this . offset . radius *= Math . pow ( this . dollySpeed , event . deltaY ) ;
76
103
}
0 commit comments