본문 바로가기

FrontEnd

CSS 애니메이션 : 설계

반응형

Types of animation

작가 Rachel Nabors는 그녀의 놀라운 책 “Animation At Work”에서 애니메이션의 5가지 일반적인 범주를 설명합니다.
  1. Transition : 한 페이지에서 다른 페이지로 이동
    • 모달 열기 또는 닫기, 다음 단계로 이동하는 다단계 마법사와 같이 페이지의 내용을 상당히 변경합니다.
  2. Supplements : "위치" 또는 작업을 변경하지 않고 페이지에서 정보를 추가하거나 제거합니다.
    • 예를 들어 알림이 모서리에 나타날 수 있습니다.
  3. Feedback : 사용자가 애플리케이션이 사용자 입력에 어떻게 응답했는지 이해하는 데 도움이 됩니다.
    • 예를 들어, 양식을 제출할 때 나타나는 오류 메시지 또는 클릭 시 아래로 미끄러지는 버튼이 눌러져 있음을 나타냅니다.
  4. Demonstration :  사용자에게 작동 방식을 보여주는 교육용으로 사용됩니다.
    • "마친 겹침 규칙" 강의의 시각화와 같은 예시입니다.
  5. Decoration은 미적이며 페이지의 정보에 영향을 미치지 않습니다.
    • 예를 들어 사용자에게 전달되는 좋은 소식을 축하하기 위한 색종이 조각입니다.

우리가 추가하는 모든 애니메이션에는 목적이 있어야 합니다.

우리는 단지 화려하기 위해 애니메이션을 추가해서는 안됩니다.

애니메이션은 제품을 더 세련된 느낌으로 만들 수 있지만, 사용자에게 애니메이션의 존재 이유가 명확할 때만 가능합니다.

현실주의

자연 세계의 사물은 순간이동 하지 않습니다.
애니메이션이 사물이 현실에서 움직이는 방식을 시뮬레이션하여
제품을 더 "현실적으로" 느끼게 만들 수 있습니다.

저는 "현실주의" 애니메이션이 #3, 피드백의 하위 집합이라고 말하고 싶습니다.
클릭, 호버링, 스크롤 등 애플리케이션이 입력에 응답하는 방식을 사용자에게 보여줍니다.

 

애니메이션 지속시간

일반적으로 허용되는 지속 시간 범위는 200ms에서 500ms입니다.
확실히 예외는 있지만 제 애니메이션의 80% 이상이 그 범위에 들어갑니다.

적응형 애니메이션

게임 초기 로딩 시 컷신을 보여주고,

그 이후에 컷신이 재생될 필요가 있으면, 스킵 버튼을 보여주는 방식을 적용할 수 있습니다.


액션 주도 애니메이션

대부분은 애니메이션에 대해 생각할 때 상태 측면에서 생각합니다.
모달은 열려 있거나(불투명도: 1) 닫혀 있습니다(불투명도: 0). CSS 전환을 사용하여 상태 변경을 애니메이션으로 만듭니다.
 
이러한 사고 방식의 문제점은 행동을 구분하지 않는다는 것입니다.
모달을 여는 transition은 모달을 닫을 때와 동일합니다.
두 작업이 동일한 두 상태 사이에서 전환되기 때문입니다.
그러나 그것이 정말로 이상적인가요?
 
추천하는 모달 세팅
  • Enter duration: 500ms
  • Enter timing function: ease-out
  • Exit duration: 250ms
  • Exit timing function: ease-in

예제 1 : 호버 시 커지는 버튼

버튼이 작아지고 커지는, 피드백 타입 애니메이션은 모달과 같이 차단 전환 프로세스가 아니므로,

미묘하게 작아지는 것처럼 작아지는 시간을 느리게 할 수 있습니다.

<style>
    .button {
      /* Exit animations */
      transition: transform 500ms;
    }
    .button:hover {
      transform: scale(1.1);

      /* Enter animation */
      transition: transform 200ms;
    }
    .button {
    width: 200px;
    height: 50px;
    border-radius: 6px;
    border: 2px solid;
    will-change: transform;
  }
</style>

<button class="button">
  Hello World
</button>​

예제 2 : 모달

사용자 인터랙션 기반 상태를 이용해야 하므로, js가 필요합니다.

const ENTER_DURATION = '500ms';
const EXIT_DURATION = '250ms';
const ENTER_EASE = 'ease-out';
const EXIT_EASE = 'ease-in';
function Modal({ isOpen, children }) {
  return (
    <Wrapper
      style={{
        '--transition-duration': isOpen
          ? ENTER_DURATION
          : EXIT_DURATION,
        '--timing-function': isOpen
          ? ENTER_EASE
          : EXIT_EASE,
      }}
    >
      <DialogContent>
        {children}
      </DialogContent>
    </Wrapper>
  )
}
const Wrapper = styled(DialogOverlay)`
  transition:
    transform var(--transition-duration) var(--timing-function);
`;

전체 코드 및 동작하는 예제 보기

https://courses.joshwcomeau.com/playground/modal-transitions

예제 : Pushable Button

보통 버튼은 보더나 그림자를 이용하지만, transition을 통해 더 부드러운 효과를 얻을 수 있습니다.

3차원 버튼

위 버튼은 세 가지 효과를 갖습니다.

  1. Hovering
  2. Clicking
  3. Leaving (moving the mouse away from the button)

테스트 해보기

<style>
    .front {
      transform: translateY(-4px);
      transition: transform 500ms;
    }
    .pushable:hover .front {
      transform: translateY(-6px);
      transition: transform 250ms;
    }
    .pushable:active .front {
      transform: translateY(-2px);
      transition: transform 50ms;
    }
    .pushable {
    background: hsl(340deg 100% 40%);
    border: none;
    border-radius: 12px;
    padding: 0;
    cursor: pointer;
  }
  .front {
    display: block;
    padding: 12px 42px;
    border-radius: 12px;
    font-size: 1.25rem;
    background: hsl(345deg 100% 70%);
    color: white;
  }
</style>

<button class="pushable">
  <span class="front">
    Push me
  </span>
</button>

위 솔루션을 리액트를 활용하여 액션 기반 애니메이션으로 리팩토링 할 수 있습니다.

function Button({ children }) {
  /*
  We track 4 actions:
    • "hovering", the user is mousing over the button
    • "depressed", the user is pressing down on it
    • "released", the user has released the button
    • "exited", the user has moused away
  */
  const [
    mostRecentAction,
    setMostRecentAction
  ] = React.useState(null);
  /* Calculate the right styles based on the action */
  let styles = {};
  if (mostRecentAction === 'hovering') {
    styles = {
      transform: 'translateY(-6px)',
      transition: 'transform 250ms',
    }
  } else if (mostRecentAction === 'depressed') {
    styles = {
      transform: 'translateY(-2px)',
      transition: 'transform 50ms',
    }
  } else if (mostRecentAction === 'released') {
    styles = {
      transform: 'translateY(-6px)',
      transition: 'transform 200ms',
    }
  } else {
    // The default value
    // Used initially, before any actions have occurred, and also
    // when exiting.
    styles = {
      transform: 'translateY(-4px)',
      transition: 'transform 500ms',
    }
  }
  return (
    <button
      style={styles}
      // Set the action based on the JS event:
      onMouseEnter={() => setMostRecentAction('hovering')}
      onMouseDown={() => setMostRecentAction('depressed')}
      onMouseUp={() => setMostRecentAction('released')}
      onMouseLeave={() => setMostRecentAction('exited')}
    >
      {children}
    </button>
  );
}

애니메이션 오케스트레이션

애니메이션의 순서는 생각보다 중요합니다.

한번에 모든 전환이 시작되는 것보다 더 자연스러운 애니메이션을 만들 수 있습니다.

  • 배경은 즉시 페이드 인되기 시작하여 오랜 시간(1000ms) 지속됩니다.
  • 모달은 250ms 동안 기다린 다음 400ms 이상 미끄러집니다.
  • 닫기 버튼은 이제 기본적으로 숨겨져 있으며 고유한 전환이 제공됩니다. 600ms 후에 애니메이션을 시작하고 250ms 동안 지속됩니다.

모달이 나타날 때
모달이 나갈 때

위 예제 보기 : https://courses.joshwcomeau.com/playground/modal-orchestrations

 

이런 효과를 가장 잘쓰는 회사는 바로 apple.com 입니다.

위 홈페이지에서 검색 버튼을 눌러보면 다음과 같은 효과를 경험할 수 있습니다.

  1. 배경이 페이드 인
  2. 헤더 네비게이션이 페이드 아웃
  3. 드롭다운이 페이드 인
  4. 드롭다운이 표시되면 드롭다운 항목이 나타납니다
  5. 드롭다운 위의 검색 인풋과 및 닫기 버튼이 슬라이드 인

transitionEnd 이벤트

한 애니메이션 종료 시 다른 애니메이션 트리거

element.addEventListener('onTransitionEnd', () => {
  // Whenever a transition completes on the target element,
  // this function will be called.
});

참고 자료

Animation At Work

 

Animation at Work by Rachel Nabors

Animation isn’t merely decorative—it’s an invaluable tool for creating a better web.

abookapart.com

Improving the Payment Experience With Animations

 

Improve the payment experience with animations

Behind the scenes of Stripe Checkout

medium.com

“Building a Magical 3D Button”

 

Building a Magical 3D Button

Every action we take on the web starts with a button click, and yet most buttons are ho-hum and uninspired. In this tutorial, we'll build an animated 3D button with HTML and CSS that sparks joy.

www.joshwcomeau.com

Meaningful Motion with Action-Driven Animation

 

Meaningful Motion with Action-Driven Animation

Simple guiding principles for making animations more meaningful

tobiasahlin.com

 

반응형