offset-path로 곡선 이동 애니메이션 만들기

Alchemist·2025년 8월 5일

CSS

목록 보기
2/6

라이브 커머스, 쇼핑몰, 인터랙티브 웹 UI에서 종종 볼 수 있는
웹에서 상품을 장바구니에 추가할 때, "슝~ 날아가는 애니메이션"을 본 적 있으신가요?

이번 글에서는 offset-path를 중심으로
1. CSS만으로 만든 기본 예제
2. JavaScript로 두 요소 간 경로를 동적으로 계산한 확장 예제를 각각 소개합니다.

🎯 지원 브라우저:

✅ Chrome, Edge, Opera, Brave
⚠️ Safari는 offset-path 미지원
❌ IE, Firefox 미지원


🎯 목표

  • 상품 → 장바구니 방향으로 곡선 이동 애니메이션 구현
  • offset-pathoffset-distance를 이용해 자연스러운 궤적 구현
  • CSS만으로 가능한 버전과, JavaScript로 확장한 버전을 각각 비교

예제 1. CSS만으로 구현한 장바구니 애니메이션

📌 특징:

  • offset-path에 고정 경로(path)를 미리 지정
  • 버튼 클릭 시 .active 클래스를 붙여 애니메이션 실행

🧱 HTML 구조

<div class="container">
  <div class="cart-icon" id="cartIcon"></div>
  <button id="start">애니메이션 실행</button>
</div>

🎨 CSS (핵심 스타일)

.container {
  position: relative;
  height: 500px;
  background: #f9f9f9;
}

.cart-icon {
  width: 44px;
  height: 44px;
  background: tomato;
  border-radius: 50%;
  position: absolute;
  offset-rotate: 0deg;
  display: none;
}

.cart-icon.active {
  display: block;
  offset-path: path("M 100 400 C 100 100, 500 100, 500 400");
  animation: moveCart 1.2s ease-in-out forwards;
}

🌀 애니메이션 키프레임

@keyframes moveCart {
  from {
    offset-distance: 0%;
  }
  to {
    offset-distance: 100%;
  }
}

🧠 JavaScript

document.getElementById("start").addEventListener("click", () => {
  const cart = document.getElementById("cartIcon");
  cart.classList.remove("active");
  void cart.offsetWidth; // 리플로우
  cart.classList.add("active");
});

✨ 예제 2. JavaScript로 요소 위치 기반으로 경로 생성

📌 특징:

  • getBoundingClientRect()로 두 요소의 좌표 계산
  • JS에서 offset-path에 동적 경로 삽입
  • 다양한 위치에서도 자유롭게 애니메이션 가능

🧱 HTML 구조

<div class="container">
  <div class="start-point" id="product">상품</div>
  <div class="end-point" id="cart">장바구니</div>
  <div class="cart-icon" id="badge"></div>
  <button id="move">장바구니 담기</button>
</div>

🎨 CSS (핵심 스타일)

.container {
  position: relative;
  height: 500px;
  background: #f0f0f0;
}

.start-point,
.end-point {
  position: absolute;
  width: 60px;
  height: 60px;
  background: #ccc;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.start-point {
  top: 350px;
  left: 100px;
}

.end-point {
  top: 100px;
  left: 500px;
}

.cart-icon {
  position: fixed;
  width: 44px;
  height: 44px;
  background: tomato;
  border-radius: 50%;
  display: none;
  offset-rotate: 0deg;
  z-index: 9999;
}

.cart-icon.active {
  display: block;
  animation: moveCart 1.2s ease-in-out forwards;
}

🌀 애니메이션 키프레임

@keyframes moveCart {
  from {
    offset-distance: 0%;
  }
  to {
    offset-distance: 100%;
  }
}

🧠 JavaScript

const product = document.getElementById("product");
const cart = document.getElementById("cart");
const badge = document.getElementById("badge");
const button = document.getElementById("move");

button.addEventListener("click", () => {
  const start = product.getBoundingClientRect();
  const end = cart.getBoundingClientRect();

  const startX = start.left + start.width / 2;
  const startY = start.top + start.height / 2;
  const endX = end.left + end.width / 2;
  const endY = end.top + end.height / 2;

  const peak = 300;
  const path = `M ${startX} ${startY} C ${startX} ${startY - peak}, ${endX} ${endY - peak}, ${endX} ${endY}`;

  badge.classList.remove("active");
  badge.getAnimations().forEach(a => a.cancel());
  void badge.offsetWidth;

  badge.style.setProperty("offset-path", `path("${path}")`);
  badge.classList.add("active");

  badge.addEventListener("animationend", () => {
    badge.classList.remove("active");
    badge.style.removeProperty("offset-path");
  }, { once: true });
});

🔍 두 예제 비교

항목CSS 버전JavaScript 확장 버전
동작 방식고정 경로 사용요소 좌표 기반 경로 생성
유연성제한적 (위치 고정 필요)어떤 위치든 대응 가능
유지보수간단함다소 복잡하지만 강력함
실전 적용정적인 UI동적 UI, 실서비스에 적합

🔍 핵심 속성 정리

속성설명예시
offset-path요소가 이동할 경로 (SVG path 가능)offset-path: path("M 0 0 C ...")
offset-distance경로를 따라 이동하는 거리 비율0% ~ 100%
offset-rotate회전 방향 고정0deg 또는 auto
animation애니메이션 속도 및 반복 설정animation: moveCart 1.2s ease

🧑‍🏫 포인트 요약

  • offset-path는 CSS에서 지정한 SVG path를 따라 이동시킬 수 있는 강력한 기능!
  • 단, 지원 브라우저가 제한적이므로 사용자층 고려 필요.
  • display: none으로 숨기고 .active로 트리거하는 방식이 일반적.
  • JavaScript는 단순히 클래스 토글 용도로만 사용 가능.

🧪 실전 팁

  • M x y C x1 y1, x2 y2, x y 형태의 베지어 곡선 경로는 SVG Path Editor를 구글링해서 만들기
  • offset-rotate: auto로 설정하면 이동 방향에 따라 회전도 자동으로 됩니다.

📝 마무리

offset-path는 현대 CSS에서 매우 강력한 도구입니다.
CSS만으로도 기본 애니메이션은 충분히 만들 수 있고,
JavaScript를 함께 사용하면 더 강력한 동적 인터랙션을 구현할 수 있습니다.

profile
html_programming_language

0개의 댓글