transform으로 3D 느낌나는 눈알 애니메이션 만들기

soyeon·2024년 4월 9일
0

TIL

목록 보기
32/32
post-custom-banner

작년에 제작한 프로모션 페이지에서 Web animation apitransform을 활용해 360도 회전하는 구체 애니메이션을 구현했다.

직접 3D UI를 구현하기 위해 Three.js를 사용하면 더 좋은 경험이 될 테지만, 빠르게 구현하고자 할 때는 이 튜토리얼을 참고하면 좋을 것이다.

DOM 조작의 편의성을 위해 Vue.js로 코드를 작성했다.

애니메이션 관련 코드 자체는 바닐라 JS로도 충분히 구현할 수 있다.

Web Animation API에 대해

Web Animation API를 사용하면 자바스크립트로 애니메이션을 생성하고 제어할 수 있다.

CSS 애니메이션 작성 방법을 알고 있다면 이를 쉽게 구현할 수 있다.

재생을 제어할 수 있고, 애니메이션에 대한 CSS 속성을 작성하거나 클래스를 만들 필요가 없다. 무엇보다도, 애니메이션의 값을 동적으로 설정할 수 있다.

개인적인 의견으로는, 아래의 상황에서 사용하는 것이 좋다.

  1. UI와 인터렉션 코드를 분리하고 싶을 때
  2. 스크립트에서 애니메이션을 제어해야할 때
  3. 애니메이션의 속성값을 동적으로 설정하고 싶을 때
  4. 복잡한 애니메이션을 구현해야할 때 ex)연속으로 이어지는 애니메이션

마크업

눈알 마크업은 이 아티클에서 가져왔다.

html

<div ref="eyeball" class="eyeball">
    <div ref="iris" class="iris"></div>

css

.eyeball {
  position: relative;
  z-index: 1;
  width: 180px;
  height: 180px;
  overflow: hidden;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 40%,
    #fcfcfc,
    #efeff1 66%,
    #9b5050 100%
  );
}

.iris {
  position: relative;
  width: 40%;
  height: 40%;
  margin: 30%;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 50%,
    #208ab4 0%,
    #6fbfff 30%,
    #4381b2 100%
  );
}

.iris:before {
  content: "";
  display: block;
  position: absolute;
  width: 37.5%;
  height: 37.5%;
  border-radius: 50%;
  top: 31.25%;
  left: 31.25%;
  background: black;
}

.iris:after {
  content: "";
  display: block;
  position: absolute;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  top: 20%;
  left: 31.25%;
  background: white;
}

애니메이션 코드 작성하기

눈알이 한바퀴를 돌 때 2개의 애니메이션이 연달아서 실행된다.

  1. 눈동자(Iris)가 가운데 → 왼쪽으로 돌아가는 애니메이션
  2. 눈동자(Iris)가 오른쪽 → 가운데로 돌아가는 애니메이션

1번 눈동자(Iris)가 가운데 → 왼쪽으로 돌아가는 애니메이션을 작성해보았다.

this.$refs.iris.animate(
        [
          { transform: "none" },
          { transform: "translate(-120%, 0%) scale(0, 0.9)" },
        ],
        {
          duration: 500,
          easing: "cubic-bezier(.57, .03, 1, 1)",
          fill: "forwards",
        }
      )



transform을 사용해 원근법이 적용된 것처럼 눈동자의 모양을 변형시켜 입체감을 더했다.
easingcubic-bezier를 사용해서 섬세한 애니메이션 움직임을 만들어주었다.

애니메이션을 실행시켜보면 이런 모습이다.

2번 눈동자(Iris)가 오른쪽 → 가운데로 돌아가는 애니메이션도 이와 비슷한 방식으로 작성하면 된다.

this.$refs.iris.animate(
        [
          { transform: "translate(120%, 0%) scale(0, 0.9)" },
          { transform: "translate(0%, 0%) scale(1, 1)" },
        ],
        {
          duration: 500,
          delay: 200,
          easing: "cubic-bezier(.11,.2,.38,1.08)",
          fill: "forwards",
        }
      )

연속되는 애니메이션 재생시키기

Animation의 finished라는 프로퍼티를 사용해서 이 두 애니메이션을 연결시켜주었다.

  1. 'finished'는 애니메이션 재생이 끝나면 promise를 반환한다..
  2. 이에 'await'를 사용하여 애니메이션이 종료될 때까지 기다린다.
  3. 그 후 다음 애니메이션이 재생되고, 그 애니메이션이 종료될 때까지 기다린다.
async ballAnimation() {
      await this.$refs.iris.animate(
        [
          { transform: "none" },
          { transform: "translate(-120%, 0%) scale(0, 0.9)" },
        ],
        {
          duration: 500,
          easing: "cubic-bezier(.57, .03, 1, 1)",
          fill: "forwards",
        }
      ).finished;
      await this.$refs.iris.animate(
        [
          { transform: "translate(120%, 0%) scale(0, 0.9)" },
          { transform: "translate(0%, 0%) scale(1, 1)" },
        ],
        {
          duration: 500,
          delay: 200,
          easing: "cubic-bezier(.11,.2,.38,1.08)",
          fill: "forwards",
        }
      ).finished;
    },

함수를 실행하면 위와 같은 애니메이션이 실행된다.

번외) transform - skew를 사용해서 눈알의 하이앵글, 로우앵글 구현하기

skew는 2d 평면에서 x, y축에 따라 요소를 비틀어주는 css 함수이다.


이 함수를 이용해서 눈동자에 입체감을 주면 된다. (디자이너랑 꼭 같이 확인하기!)


//translate는 알아서 조절 skew만 참고하세요~

//왼쪽 아래를 바라봄
transform: translate(-130%, 50%) scale(0.2, 0.8) skew(60deg, -10deg),

//오른쪽 위를 바라봄
transform: translate(125%, -50%) scale(0.2, 0.8) skew(60deg, 10deg),

참고

https://cssanimation.rocks/spheres/
https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API

profile
공부중
post-custom-banner

0개의 댓글