이번 글에서는 React Three Fiber를 이용해 간단한 애니메이션을 구현해보자.
이전 글은 아래를 참고해주세요.
【React Three Fiber】#02 오브젝트 변형하기
이전 글은 아래를 참고해주세요. 【React Three Fiber】#01 시작하기(초기 설정, 정육면체 렌더링) 【React Three Fiber】#01 시작하기(초기 설정, 정육면체 렌더링) 현재 일본 파견회사에서 3년 이상(4년 차)
solitary-choi.tistory.com
2편과 마찬가지로, 이번에도 1편에서 작성했던 Basic.tsx을 복사해 컴포넌트명만 변경해준다.
Animation.tsx
/* eslint-disable react/no-unknown-property */
import { Canvas } from "@react-three/fiber";
import React from "react";
import classes from "../styles/Global.module.css";
const Cube = () => {
const object = (
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
);
return object;
};
const Animation = () => {
return (
<div className={classes.canvas}>
<Canvas camera={{ position: [1, 1, 3] }}>
<Cube />
</Canvas>
</div>
);
};
export default Animation;
App.tsx
import Animation from "./components/Animation";
import React from "react";
function App() {
return <Animation />;
}
export default App;
useFrame()
1 프레임마다 콜백 함수를 실행시키는 React Three Fiber 커스텀 훅이다.
여기서의 1 프레임은 60 fps이며, 이는 1초당 60회 콜백 함수를 실행시킨다는 것을 의미한다.
Position
그러면 useFrame을 사용해, 우선은 오브젝트를 오른쪽으로 움직이게 해 보자.
2편에서 언급했듯, mesh의 속성을 수정하고 싶다면 useRef를 사용하면 된다.
import { Canvas, useFrame } from "@react-three/fiber";
import React, { useRef } from "react";
const Cube = () => {
const cubeRef = useRef<THREE.Mesh>(null);
useFrame((state) => {
if (!cubeRef.current) {
return;
}
cubeRef.current.position.x += 0.01;
});
const object = (
<mesh ref={cubeRef}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
);
return object;
};
위의 코드를 실행하면 아래와 같이 오른쪽으로 오브젝트가 이동하는 것을 확인할 수 있다.
getElapsedTime()
이번에는 경과시간을 이용해서 오브젝트를 움직여보자.
useFrame의 state에 내장되어 있는 clock의 getElapsedTime()을 사용하면 clock이 생성되고 나서 경과된 시간을 구할 수 있다.
useFrame((state) => {
if (!cubeRef.current) {
return;
}
const elapsedTime = state.clock.getElapsedTime();
cubeRef.current.position.y = elapsedTime;
});
위의 코드를 실행해 오브젝트가 위로 이동하는 것을 확인해보자.
sin(x)나 cos(x)를 사용함으로써 오브젝트가 상하로 움직임을 반복하게도 할 수 있다.
sin(x)
0(중간지점)에서부터 시작해, 상하로 반복된다.
코드로 작성하면 이런 느낌이다.
cubeRef.current.position.y = Math.sin(elapsedTime);
다음과 같이 오브젝트가 중간지점에서부터 시작해 상하로 움직임을 반복하는 것을 볼 수 있다.
cos(x)
1(최상단)에서부터 시작해, 상하로 반복된다.
아래 코드를 실행하면, 오브젝트가 오른쪽에서부터 시작해 좌우로 반복해서 움직이게 된다.
cubeRef.current.position.x = Math.cos(elapsedTime);
참고로, ref의 position속성을 변경하는 것이 아닌, state에 내장되어 있는 카메라의 속성을 변경해도 거의 흡사한 애니메이션 효과를 줄 수 있다.
아래의 코드를 실행하면 정육면체가 원을 그리며 회전하게 된다.
state.camera.position.y = Math.sin(elapsedTime);
state.camera.position.x = Math.cos(elapsedTime);
camera.lookAt()
원점 좌표(0, 0, 0)를 지정한다.
위의 코드와 함께 사용하여, 지정한 오브젝트를 중심으로 카메라를 회전시킬 수 있다.
state.camera.lookAt(cubeRef.current.position);
Rotation
이때까지 position을 변경해서 오브젝트를 움직이게 해 봤는데, rotation을 변경해 회전시키는 것도 가능하다.
방법은 position과 흡사하게, useFrame에서 ref의 rotation속성을 변경하면 된다.
cubeRef.current.rotation.y += 0.01;
그러면 아래와 같이 오브젝트가 빙글빙글 돌아가는 것을 확인할 수 있다.
느릿느릿 돌아가는 정육면체가 왠지 모를 안정감을 준다.
아까 정의한 elapsedTime과 라디안을 이용해 엄청난 스피드로 회전하게 할 수도 있다. (솔직히 정신사납다.)
cubeRef.current.rotation.y = elapsedTime * Math.PI * 2;
gsap
GreenSock에서 제작한 자바스크립트 애니메이션 라이브러리라고 한다.
얼핏 봐서는 three.js뿐만 아니라 2D에서도 사용할 수 있는 듯하다.
다음 커맨드를 실행해 gsap를 설치해주자.
npm install --save gsap
그리고 다음 코드를 작성해주자.
이번에는 애니메이션을 한 번만 실행할 예정이니, useFrame대신 useEffect를 사용한다.
아까 사용했던 useFrame은 주석 처리를 하거나 지워도 상관없다.
gsap.to()
목적지의 상태를 지정한다.
다음 코드의 경우, 1초 뒤 1초 동안 오른쪽으로 2만큼 이동한 후, 2초 뒤 1초 동안 원점으로 돌아오게 한다는 의미이다.
const Cube = () => {
const cubeRef = useRef<THREE.Mesh>(null);
useEffect(() => {
if (!cubeRef.current) {
return;
}
gsap.to(cubeRef.current.position, { duration: 1, delay: 1, x: 2 });
gsap.to(cubeRef.current.position, { duration: 1, delay: 2, x: 0 });
}, []);
const object = (
<mesh ref={cubeRef}>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="#e91e63" />
</mesh>
);
return object;
};
つづく
'개발 > React : React Three Fiber' 카테고리의 다른 글
【React Three Fiber】#03 카메라: Orthographic Camera, OrbitControls (0) | 2023.08.27 |
---|---|
【React Three Fiber】#02 카메라: Perspective Camera (0) | 2023.08.27 |
【React Three Fiber】#01 초기설정, 튜토리얼 (0) | 2023.08.27 |
【React Three Fiber】#06 화면 리사이징 하기, 더블 클릭 시 전체 화면 모드로 변경하기 (0) | 2022.10.13 |
【React Three Fiber】#02 오브젝트 변형하기 (0) | 2022.09.26 |