애니메이션 아이콘

Animated Icon

상태가 바뀔 때 순간 전환하지 않고 이전 모양에서 다음 모양으로 부드럽게 형태를 바꾸며 지나가는 아이콘.

다른 이름: Icon morphMicro-interaction icon
···
html
<div class="row">
  <div class="ic burger">
    <svg viewBox="0 0 24 24" width="100%" height="100%">
      <line class="l1" x1="4" y1="7" x2="20" y2="7"/>
      <line class="l2" x1="4" y1="12" x2="20" y2="12"/>
      <line class="l3" x1="4" y1="17" x2="20" y2="17"/>
    </svg>
  </div>
  <div class="ic playpause">
    <svg viewBox="0 0 24 24" width="100%" height="100%">
      <g class="pause"><rect x="7" y="5" width="3.4" height="14" rx="1"/><rect x="13.6" y="5" width="3.4" height="14" rx="1"/></g>
      <path class="play" d="M8 4.5v15l12-7.5Z"/>
    </svg>
  </div>
  <div class="ic checkmark">
    <svg viewBox="0 0 24 24" width="100%" height="100%">
      <circle cx="12" cy="12" r="9" fill="none" stroke-width="2" pathLength="100"/>
      <path d="M7.5 12.5l3 3 6-6.5" fill="none" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" pathLength="100"/>
    </svg>
  </div>
</div>
css
.row{display:flex;gap:clamp(14px,5vmin,30px);align-items:center}
.ic{width:clamp(30px,10vmin,48px);height:clamp(30px,10vmin,48px)}
.burger line{stroke:var(--fg);stroke-width:2;stroke-linecap:round;transform-origin:12px 12px}
.burger .l1{animation:burgerTop 3.6s ease-in-out infinite}
.burger .l2{animation:burgerMid 3.6s ease-in-out infinite}
.burger .l3{animation:burgerBot 3.6s ease-in-out infinite}
@keyframes burgerTop{0%,40%{transform:translateY(0) rotate(0)}55%,90%{transform:translateY(5px) rotate(45deg)}100%{transform:translateY(0) rotate(0)}}
@keyframes burgerMid{0%,40%{opacity:1}50%,95%{opacity:0}100%{opacity:1}}
@keyframes burgerBot{0%,40%{transform:translateY(0) rotate(0)}55%,90%{transform:translateY(-5px) rotate(-45deg)}100%{transform:translateY(0) rotate(0)}}
.playpause .pause,.playpause .play{fill:var(--fg)}
.playpause .pause{animation:ppA 3.2s ease-in-out infinite}
.playpause .play{opacity:0;animation:ppB 3.2s ease-in-out infinite}
@keyframes ppA{0%,45%{opacity:1}55%,100%{opacity:0}}
@keyframes ppB{0%,45%{opacity:0}55%,100%{opacity:1}}
.checkmark circle{stroke:var(--line)}
.checkmark path{stroke:var(--accent-3);stroke-dasharray:100;animation:checkDraw 3s ease-in-out infinite}
@keyframes checkDraw{0%,10%{stroke-dashoffset:100}45%,80%{stroke-dashoffset:0}100%{stroke-dashoffset:-100}}

애니메이션 아이콘은 상태가 바뀔 때 순간적으로 전환하지 않고, 이전 모양에서 다음 모양으로 부드럽게 형태를 바꾸며 지나간다. 햄버거 메뉴가 X로 변하는 것, 재생 버튼이 일시정지로 바뀌는 것, 체크박스에 체크 표시가 그려지는 것이 대표적인 예다. 정적인 아이콘 교체보다 "지금 상태가 바뀌었다"는 사실을 훨씬 분명하게 전달한다.

구현 방식은 크게 두 가지다. 하나는 선이나 도형 자체를 회전·이동시켜 진짜로 모양이 변하게 만드는 트랜스폼 방식(햄버거→X가 대표적)이고, 다른 하나는 두 상태를 겹쳐두고 투명도만 교차시키는 크로스페이드 방식이다. 체크 표시처럼 "그려지는" 느낌을 주려면 스트로크를 실제로 획 순서대로 나타나게 하는 stroke-dashoffset 애니메이션을 쓴다.

지속 시간은 보통 150~300ms로 짧게 잡는다. 너무 길면 사용자가 다음 동작으로 넘어가지 못해 답답해하고, 너무 짧으면 무슨 일이 일어났는지 인지하지 못한다. 또한 애니메이션이 끝난 뒤의 최종 모양이 실제 상태(메뉴가 열렸다/재생 중이다)와 정확히 일치해야 한다 — 애니메이션은 예쁘지만 상태가 틀리면 오히려 신뢰를 깎는다.

언제 쓰나

메뉴 열기/닫기, 재생/일시정지, 완료 표시처럼 상태 전환이 명확히 인지돼야 하는 토글 버튼에 쓰세요. 150~300ms 안팎으로 짧게 잡고, 끝난 뒤의 모양이 실제 상태와 반드시 일치하게 하세요.