[Three.js] Animation 구현하기

seongminn·2022년 6월 11일
2

JavaScript

목록 보기
3/5
post-thumbnail
post-custom-banner

📌 Animation

지난 시간에 이어, Three.js에서 각종 애니메이션을 구현해보자.

requestAnimationFrame

Javascript에서 웹 애니메이션을 구현하는 방법은 setInterval을 이용하는 방법, requestAnimationFrame을 이용하는 방법으로 크게 2가지가 있다. 하지만, setInterval은 애초에 애니메이션을 위해 생겨난 메서드가 아니며, 불필요한 콜스택(callstack)이 지나치게 많이 발생하여 애니메이션에 딜레이가 발생할 수 있다.

requestAnimationFrame을 활용한다면 이러한 문제를 쉽게 해결할 수 있다. requestAnimationFrame은 반복할 함수를 인자로 받는다. 그리고 해당 인자를 1초에 최대 60번 실행하여 호출 스택이 과도하게 커지는 것을 방지한다. 그래서 딜레이 없이 부드러운 애니메이션을 확인할 수 있다.

또한, requestAnimationFrame은 페이지가 비활성 상태라면 랜더링을 중지하기 때문에 CPU 리소스와 배터리 수명을 낭비하지 않는다. 즉, 성능 향상에 도움이 된다.

이런 이유로, 이번 프로젝트에서 애니메이션을 구현하기 위해서는 requestAnimationFrame을 사용할 것이다.

Animate 함수 호출

먼저, 3D 객체를 랜더링하기 위해 작성했던 코드를 살펴보자.

loader.load("duck/scene.gltf", function (gltf) {
  scene.add(gltf.scene);
  renderer.render(scene, camera);
});

3D 모델을 로드한 뒤, 이를 Scene 객체에 추가하고 랜더링하는 과정을 거쳤다. 이 때, 콜백 함수에 애니메이션을 위한 함수를 추가할 수 있다. 그리고 이 애니메이션 함수를 requestAnimationFrame 메서드를 활용하여 재귀적으로 호출할 것이다.

애니메이션 함수 안에는 3D 요소의 움직임에 관련한 코드를 추가한다. y축을 기준으로 1/60s마다 0.005만큼 회전시키고, 리랜더링을 시켜준다.

loader.load("duck/scene.gltf", function (gltf) {
  scene.add(gltf.scene);
  
  function animate() {
    requestAnimationFrame(animate);
    gltf.scene.rotation.y += 0.005;
    renderer.render(scene, camera);
});

한 바퀴 회전하기 위해서는 360도, 즉 2 * PI만큼 회전해야 하기 때문에 rotation 값이 총 6.283···에 근접했을 때 1회전한다. 결국 약 20초마다 한 바퀴씩 회전하는 오리를 확인할 수 있다.


OrbitControls

다음으로는 마우스 드래그와 휠을 사용하여 카메라를 제어하는 방법을 알아보도록 하자.

먼저, CDN 방식을 사용하여 OrbitControls를 불러온다.

      import { 
        OrbitControls
      } from "https://cdn.jsdelivr.net/npm/three@0.124/examples/jsm/controls/OrbitControls.js";

그리고 controls라는 변수에 OrbitControls 객체를 저장해준다. 이 때, OrbitControls 생성자 함수가 전달 받는 인자는 제어하고자 하는 카메라 객체와 이벤트를 탐지할 HTML Element이다. 마우스 드래그와 휠에 의한 이벤트는 renderer 객체가 3D 요소를 랜더링하고자 하는 공간인 Canvas에서 발생하기 때문에 인자로 renderer.domElement를 넘겨준다. renderer.domElement는 앞서 그린 것들이 담겨 있는 Canvas 태그이다.

let controls = new OrbitControls(camera, renderer.domElement);

console.log(renderer.domElement);
// <canvas id="canvas" width="1920" height="452" data-engine="three.js r138" style="width: 1920px; height: 452px;"></canvas>

그리고 이벤트가 발생할 때마다 변경된 내용을 업데이트하기 위해 animate 함수 내에 controls.update()를 추가해준다.

loader.load("duck/scene.gltf", function (gltf) {
  scene.add(gltf.scene);
  
  function animate() {
    requestAnimationFrame(animate);
    gltf.scene.rotation.y += 0.005;
    renderer.render(scene, camera);
    controls.update();
});

이제 마우스를 활용한 이벤트로 카메라를 조작할 수 있다.

Mouse Event

  • Left Click & Drag 카메라 회전
  • Wheel 줌 (Dolly)
  • Right Click & Drag 카메라 위치 변경

Controls Properties

controls.enableDamping = true; // 카메라 조작 시 부드러운 동작을 가능하게 한다. 
controls.rotateSpeed = 0.8; // 카메라 회전 속도를 조절한다.
controls.zoomSpeed = 1.2; // 카메라를 줌 할 때의 속도를 조절한다.

--

참고 사이트

🙇🏻‍♂️ https://velog.io/@whdnjsdyd111/Three.js-%EA%B0%9C%EB%B0%9C-%ED%8C%81
🙇🏻‍♂️ https://syrang.tistory.com/10

profile
돌멩이도 개발 할 수 있다
post-custom-banner

0개의 댓글