배경을 비디오 처리하고, overlay와 3D Geometry 을 위에 구현해 본 코드입니다.
// App.jsx
import bgVideo from "./assets/seokang-background.mp4";
import RenderModel from "./components/RenderModel";
import Blocks from "./components/models/Blocks";
function App() {
return (
<main className="relative min-h-screen flex items-center justify-center">
<video
className="absolute top-0 left-0 w-full h-full object-cover"
src={bgVideo}
autoPlay
loop
muted
/>
{/* <div className="absolute inset-0 bg-black bg-opacity-70"></div> */}
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-60 z-10"></div>
<div className="w-full h-screen absolute z-20 flex justify-center items-center">
<RenderModel>
<Blocks />
</RenderModel>
</div>
</main>
);
}
export default App;
// Blocks.jsk
/* eslint-disable */
import React, { useRef, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { Canvas, useFrame } from "@react-three/fiber";
import * as THREE from "three";
function createMesh(geometry, material, position, name) {
const mesh = new THREE.Mesh(geometry, material.clone());
mesh.position.set(...position);
mesh.name = name;
mesh.castShadow = true;
mesh.receiveShadow = true;
return mesh;
}
function Box({ geometry, material, position, name }) {
const navigate = useNavigate();
const mesh = useMemo(
() => createMesh(geometry, material, position, name),
[geometry, material, position, name]
);
// Random color generation
const color = useMemo(
() => new THREE.Color(Math.random(), Math.random(), Math.random()),
[]
);
mesh.material.color = color;
const handlePointerOver = (event) => {
document.body.style.cursor = 'pointer';
};
const handlePointerOut = (event) => {
document.body.style.cursor = 'default';
};
const handleClick = (event) => {
navigate(`/${name}`);
};
return (
<mesh
position={position}
castShadow
receiveShadow
onPointerOver={handlePointerOver}
onPointerOut={handlePointerOut}
onClick={handleClick}
>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial attach="material" color={color} />
</mesh>
);
}
const Blocks = React.memo(function Blocks(props) {
const modelRef = useRef();
// Define geometry and material within Blocks
const boxGeometry = useMemo(() => new THREE.BoxGeometry(1, 1, 1), []);
const material = useMemo(() => new THREE.MeshStandardMaterial(), []);
useFrame((state) => {
modelRef.current.position.y =
-1.5 + Math.sin(state.clock.elapsedTime) * 0.15;
});
return (
<group
{...props}
dispose={null}
ref={modelRef}
position={[0, 1, 0]} // y축 값을 변경하여 위치 조정
scale={[1, 1, 1]} // scale 값을 변경하여 크기 조정
>
<Box
geometry={boxGeometry}
material={material}
position={[1.5, 0, 0]} // 오른쪽
name="Box A"
/>
<Box
geometry={boxGeometry}
material={material}
position={[-1.5, 0, 0]} // 왼쪽
name="Box B"
/>
<Box
geometry={boxGeometry}
material={material}
position={[0, 1.5, 0]} // 위
name="Box C"
/>
<Box
geometry={boxGeometry}
material={material}
position={[0, -1.5, 0]} // 아래
name="Box D"
/>
</group>
);
});
export default Blocks;
이미지 매핑하기 (1) | 2024.11.24 |
---|---|
touch event - @react-three/fiber (2) | 2024.11.23 |
resize - Three.js (0) | 2024.11.22 |
lookAt(), getWorldDirection() (1) | 2024.11.21 |
Capsule class (2) | 2024.11.21 |