Skip to content

Commit

Permalink
Merge pull request #4 from Skhuthon/feature/2
Browse files Browse the repository at this point in the history
[#3] ๋ฐฉํƒˆ์ถœ ํ…Œ๋งˆ ์ถ”์ฒœ ํ™”๋ฉด
  • Loading branch information
MyungJiwoo authored Jun 28, 2024
2 parents 9a6b700 + 41e59d1 commit 0b219e3
Show file tree
Hide file tree
Showing 16 changed files with 883 additions and 35 deletions.
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react-scripts": "5.0.1",
"styled-components": "^6.1.11",
"three": "^0.165.0",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down Expand Up @@ -45,6 +46,7 @@
},
"devDependencies": {
"@types/styled-components": "^5.1.34",
"@types/three": "^0.165.0",
"typescript": "^4.9.5"
}
}
13 changes: 11 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@ import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import MainPage from "./pages/MainPage";
import ThemeRecs from "./pages/ThemeRecs";
import ThemeRecsQuestions from "./pages/ThemeRecsQuestions";
import ThemeRecsResult from "./pages/ThemeRecsResult";
import Navbar from "./components/Navbar";

const App: React.FC = () => {
return (
<Router>
<Navbar />
<Routes>
<Route path="/" Component={MainPage} />
<Route path="/themeRecs" Component={ThemeRecs} />
<Route path="/" element={<MainPage />} />
<Route path="/themeRecs" element={<ThemeRecs />} />
<Route
path="/ThemeRecsQuestions"
element={<ThemeRecsQuestions />}
/>
<Route path="/themeRecsResult" element={<ThemeRecsResult />} />
</Routes>
</Router>
);
Expand Down
41 changes: 25 additions & 16 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Container } from "../styles/NavbarStyled";
import { Container, NavLink } from "../styles/NavbarStyled";
import logo from "../image/bangpro_logo.png";
import { BsChatSquareHeartFill } from "react-icons/bs";
import { BsCollectionFill } from "react-icons/bs";
Expand All @@ -11,25 +11,34 @@ const Navbar = () => {
<div className="logoBox">
<img src={logo} alt="logo" className="logo"></img>
</div>

<div className="navBox">
<div className="nav1">
<div>
<BsChatSquareHeartFill />
<NavLink to={`/themeRecs`}>
<div className="nav">
<div>
<BsChatSquareHeartFill />
</div>
<p>ํ…Œ๋งˆ ์ถ”์ฒœ</p>
</div>
<p>ํ…Œ๋งˆ ์ถ”์ฒœ</p>
</div>
<div className="nav2">
<div>
<BsCollectionFill />
</NavLink>

<NavLink to={`/`}>
<div className="nav">
<div>
<BsCollectionFill />
</div>
<p>ํ…Œ๋งˆ ์ •๋ณด</p>
</div>
<p>ํ…Œ๋งˆ ์ •๋ณด</p>
</div>
<div className="nav3">
<div>
<BsPersonFill />
</NavLink>

<NavLink to={`/`}>
<div className="nav">
<div>
<BsPersonFill />
</div>
<p>๋งˆ์ดํŽ˜์ด์ง€</p>
</div>
<p>๋งˆ์ดํŽ˜์ด์ง€</p>
</div>
</NavLink>
</div>
</Container>
);
Expand Down
26 changes: 26 additions & 0 deletions src/components/RoomTheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import { Theme } from "../styles/RoomThemeStyled";

const RoomTheme = () => {
return (
<Theme>
<div className="titleBox">
<p>๋ฐฉํƒˆ์ถœ ํ…Œ๋งˆ ์ด๋ฆ„</p>
</div>
<div className="addressBox">
<p>๋งค์žฅ ์ •๋ณด</p>
</div>
<div className="cardFooter">
<div className="hashtagBox">
<p>#๋‚œ์ด๋„</p>
<p>#์žฅ๋ฅด</p>
</div>
<div className="linkBtn">
<p>์˜ˆ์•ฝ ์‚ฌ์ดํŠธ</p>
</div>
</div>
</Theme>
);
};

export default RoomTheme;
4 changes: 4 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

p {
margin: 0;
}
2 changes: 0 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import Navbar from "./components/Navbar";

const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
Expand All @@ -12,7 +11,6 @@ const root = ReactDOM.createRoot(
root.render(
// strictMode์—์„œ๋Š” ๋‘๋ฒˆ ๋ Œ๋”๋ง ๋  ์ˆ˜ ์žˆ์œผ๋‚˜, ํ”„๋กœ๋•์…˜๋นŒ๋“œ ๋ชจ๋“œ์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์„๊ฒƒ
<React.StrictMode>
<Navbar />
<App />
</React.StrictMode>
);
Expand Down
142 changes: 142 additions & 0 deletions src/pages/Cube.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { useEffect, useRef, useState } from "react";
import * as THREE from "three";

const Cube = () => {
const mountRef = useRef<HTMLDivElement>(null);
const [mouseX, setMouseX] = useState(0);
const [mouseY, setMouseY] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [previousMouseX, setPreviousMouseX] = useState(0);
const [previousMouseY, setPreviousMouseY] = useState(0);
const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(
null
);
const [initialZoom, setInitialZoom] = useState(5); // ์ดˆ๊ธฐ ์คŒ ๊ฐ’์„ ์ƒํƒœ๋กœ ๊ด€๋ฆฌ

useEffect(() => {
const mount = mountRef.current;

// Scene, Camera, Renderer ์ƒ์„ฑ
const scene = new THREE.Scene();
scene.background = null; // ๋ฐฐ๊ฒฝ์„ ํˆฌ๋ช…ํ•˜๊ฒŒ ์„ค์ •

const camera = new THREE.PerspectiveCamera(
70,
mount!.clientWidth / mount!.clientHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({ alpha: true }); // alpha ์†์„ฑ์„ true๋กœ ์„ค์ •
renderer.setSize(mount!.clientWidth, mount!.clientHeight);
mount!.appendChild(renderer.domElement);

// ์กฐ๋ช…
const directionLight = new THREE.DirectionalLight(0xffffff, 1.5);
directionLight.position.set(-0.7, 1, 5);
scene.add(directionLight);

// ํ๋ธŒ ์ƒ์„ฑ (์ƒ‰์ƒ ๋ณ€๊ฒฝ)
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshPhysicalMaterial({
color: 0x03ff8d,
metalness: 1,
roughness: 0.5,
transparent: true,
opacity: 0.9,
reflectivity: 0.9,
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = initialZoom; // ์ดˆ๊ธฐ ์คŒ ๊ฐ’ ์„ค์ •

// ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ
const onMouseDown = (event: MouseEvent) => {
setIsDragging(true);
setPreviousMouseX(event.clientX);
setPreviousMouseY(event.clientY);
setInitialRotation(cube.rotation.clone()); // ํด๋ฆญ ์‹œ์ ์˜ ํšŒ์ „ ์ƒํƒœ ์ €์žฅ
setInitialZoom(camera.position.z); // ํด๋ฆญ ์‹œ์ ์˜ ์คŒ ๊ฐ’ ์ €์žฅ
};

const onMouseMove = (event: MouseEvent) => {
if (isDragging) {
const deltaX = event.clientX - previousMouseX;
const deltaY = event.clientY - previousMouseY;

if (initialRotation) {
cube.rotation.y = initialRotation.y + deltaX * 0.005;
cube.rotation.x = initialRotation.x + deltaY * 0.005;
}

setPreviousMouseX(event.clientX);
setPreviousMouseY(event.clientY);
}
};

const onMouseUp = () => {
setIsDragging(false);
};

const onWheel = (event: WheelEvent) => {
const delta = event.deltaY * 0.01;

camera.position.z -= delta;

// Limiting camera zoom
if (camera.position.z < 4) {
camera.position.z = 4;
} else if (camera.position.z > 15) {
camera.position.z = 15;
}
};

window.addEventListener("mousedown", onMouseDown);
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("mouseup", onMouseUp);
window.addEventListener("wheel", onWheel);

if (previousMouseX > 0 || previousMouseY > 0) {
cube.rotation.x -= previousMouseX;
cube.rotation.y -= previousMouseY;
}

// ๋ฐ˜์‘ํ˜• ์ฒ˜๋ฆฌ
const onWindowResize = () => {
if (mount) {
camera.aspect = mount.clientWidth / mount.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(mount.clientWidth, mount.clientHeight);
}
};
window.addEventListener("resize", onWindowResize);

// ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฃจํ”„
const animate = () => {
requestAnimationFrame(animate);

// ๊ธฐ๋ณธ ํšŒ์ „
if (!isDragging) {
cube.rotation.x += 0.005;
cube.rotation.y += 0.005;
}

renderer.render(scene, camera);
};
animate();

// ํด๋ฆฐ์—… ํ•จ์ˆ˜
return () => {
mount!.removeChild(renderer.domElement);
window.removeEventListener("mousedown", onMouseDown);
window.removeEventListener("mousemove", onMouseMove);
window.removeEventListener("mouseup", onMouseUp);
window.removeEventListener("wheel", onWheel);
window.removeEventListener("resize", onWindowResize);
};
}, [isDragging, initialRotation, initialZoom]);

return <div ref={mountRef} style={{ width: "100%", height: "100%" }} />;
};

export default Cube;
Loading

0 comments on commit 0b219e3

Please sign in to comment.