@@ -3,7 +3,7 @@ import * as THREE from "three";
33const ZOOM_DIST = 5 ; // how close the camera gets (in planet radii + offset)
44const TWEEN_SPEED = 0.07 ; // lerp factor for camera movement
55
6- export function main ( canvas ) {
6+ export function main ( canvas , onPlanetFocus ) {
77
88 const renderer = new THREE . WebGLRenderer ( { antialias : true , canvas } ) ;
99 renderer . setPixelRatio ( window . devicePixelRatio ) ;
@@ -122,11 +122,22 @@ export function main(canvas) {
122122 const raycaster = new THREE . Raycaster ( ) ;
123123 const pointer = new THREE . Vector2 ( ) ;
124124
125- let paused = false ; // are planets frozen?
126- let focusedPlanet = null ; // the planet object we zoomed into
127- let cameraTarget = null ; // THREE.Vector3 we're tweening toward
128- let lookAtTarget = null ; // THREE.Vector3 we're looking at
125+ let paused = false ;
126+ let focusedPlanet = null ;
127+ let cameraTarget = null ;
128+ let lookAtTarget = null ;
129129 let tweening = false ;
130+ let popupFired = false ;
131+
132+ // Zoom out — resets focus and starts the camera tween back to the initial position.
133+ // Called both by canvas clicks on empty space and externally (e.g. the ✕ button).
134+ function zoomOut ( ) {
135+ focusedPlanet = null ;
136+ paused = false ;
137+ tweening = true ;
138+ cameraTarget = initPos . clone ( ) ;
139+ lookAtTarget = new THREE . Vector3 ( 0 , 0 , 0 ) ;
140+ }
130141
131142 canvas . addEventListener ( 'click' , e => {
132143 const rect = canvas . getBoundingClientRect ( ) ;
@@ -138,20 +149,16 @@ export function main(canvas) {
138149 const hits = raycaster . intersectObjects ( meshes ) ;
139150
140151 if ( hits . length > 0 ) {
141- // Clicked a planet — focus it
142152 const hit = hits [ 0 ] ;
143153 focusedPlanet = planets . find ( p => p . mesh === hit . object ) ;
144- paused = true ;
145- tweening = true ;
154+ paused = true ;
155+ tweening = true ;
156+ popupFired = false ;
146157 } else {
147- // Clicked empty space — release
148- focusedPlanet = null ;
149- paused = false ;
150- tweening = true ;
151- cameraTarget = initPos . clone ( ) ;
152- lookAtTarget = new THREE . Vector3 ( 0 , 0 , 0 ) ;
158+ zoomOut ( ) ;
153159 }
154160 } ) ;
161+
155162 // ─────────────────────────────────────────────────────────────────────
156163
157164 function resizeRendererToDisplaySize ( renderer ) {
@@ -166,7 +173,6 @@ export function main(canvas) {
166173
167174 function render ( ) {
168175
169- // Advance planet orbits (only when not paused)
170176 planets . forEach ( p => {
171177 if ( ! paused ) {
172178 p . angle += p . speed * 0.008 ;
@@ -181,47 +187,30 @@ export function main(canvas) {
181187
182188 sun . rotation . y += 0.003 ;
183189
184-
185-
186-
187-
188-
189-
190- // Update the camera target each frame while focused
191- // (so the camera tracks the planet even mid-tween if it still moves slightly)
192190 if ( focusedPlanet ) {
193191 const pPos = focusedPlanet . mesh . position ;
194- // Position the camera slightly behind & above the planet relative to the origin
195192 const dir = pPos . clone ( ) . normalize ( ) ;
196193 cameraTarget = pPos . clone ( ) . add ( dir . multiplyScalar ( focusedPlanet . radius + ZOOM_DIST ) ) ;
197194 cameraTarget . y += focusedPlanet . radius * 0.8 ;
198195 lookAtTarget = pPos . clone ( ) ;
199196 }
200197
201- // Tween camera
202198 if ( tweening && cameraTarget && lookAtTarget ) {
203199 camera . position . lerp ( cameraTarget , TWEEN_SPEED ) ;
204200 currentLookAt . lerp ( lookAtTarget , TWEEN_SPEED ) ;
205201 camera . lookAt ( currentLookAt ) ;
206202
207- // Stop tweening once close enough
208203 if ( camera . position . distanceTo ( cameraTarget ) < 0.05 ) {
209204 tweening = false ;
210205
211-
212-
213-
214-
215- // POP UP HERE
216-
217-
218-
219-
220-
221-
206+ if ( focusedPlanet && ! popupFired ) {
207+ popupFired = true ;
208+ if ( typeof onPlanetFocus === 'function' ) {
209+ onPlanetFocus ( ) ;
210+ }
211+ }
222212 }
223213 } else if ( ! paused ) {
224- // Normal parallax behaviour
225214 currentOffset . x += ( targetOffset . x - currentOffset . x ) * 0.13 ;
226215 currentOffset . y += ( targetOffset . y - currentOffset . y ) * 0.13 ;
227216
@@ -234,11 +223,6 @@ export function main(canvas) {
234223 camera . lookAt ( currentLookAt ) ;
235224 }
236225
237-
238-
239-
240-
241-
242226 if ( resizeRendererToDisplaySize ( renderer ) ) {
243227 camera . aspect = canvas . clientWidth / canvas . clientHeight ;
244228 camera . updateProjectionMatrix ( ) ;
@@ -249,4 +233,6 @@ export function main(canvas) {
249233 }
250234
251235 requestAnimationFrame ( render ) ;
236+
237+ return { zoomOut } ;
252238}
0 commit comments