Skip to content

Commit 6cfc50b

Browse files
committed
added clicking on planet opening ui and closing ui functionality
1 parent 14262ef commit 6cfc50b

3 files changed

Lines changed: 66 additions & 67 deletions

File tree

package-lock.json

Lines changed: 21 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pages/home/Home.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
import styles from "./Home.module.css";
2-
import {useState, useEffect, useRef} from "react";
2+
import { useState, useEffect, useRef } from "react";
33
import LevelComponent from "../../components/LevelComponent";
44
import { main } from "./solarsystem.js";
55

66
export default function Home() {
77
const lvlNum = 4;
88
const canvasRef = useRef<HTMLCanvasElement | null>(null);
9-
10-
useEffect(() => {
11-
12-
if (!canvasRef.current) return;
13-
14-
main(canvasRef.current);
15-
}, []);
9+
const zoomOutRef = useRef<(() => void) | null>(null);
1610

1711
const [isVisible, setIsVisible] = useState(false);
1812
const [mountKey, setMountKey] = useState(0);
@@ -22,6 +16,17 @@ export default function Home() {
2216
setIsVisible(true);
2317
};
2418

19+
const handleClose = () => {
20+
setIsVisible(false);
21+
zoomOutRef.current?.();
22+
};
23+
24+
useEffect(() => {
25+
if (!canvasRef.current) return;
26+
const { zoomOut } = main(canvasRef.current, handleOpen);
27+
zoomOutRef.current = zoomOut;
28+
}, []);
29+
2530
return (
2631
<div>
2732
<header>
@@ -35,9 +40,9 @@ export default function Home() {
3540
<section className="">
3641
{isVisible && (
3742
<LevelComponent
38-
key={mountKey}
39-
onClose={() => setIsVisible(false)}
40-
lvl={lvlNum}
43+
key={mountKey}
44+
onClose={handleClose}
45+
lvl={lvlNum}
4146
/>
4247
)}
4348
<canvas ref={canvasRef} className={styles.solarsystem}></canvas>

src/pages/home/solarsystem.js

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as THREE from "three";
33
const ZOOM_DIST = 5; // how close the camera gets (in planet radii + offset)
44
const 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

Comments
 (0)