CSS: 경로를 따라 이동하는 애니메이션 만들기 🛣️ (offset-path, ray)

두선아 Dusuna·2025년 3월 15일

CSS

목록 보기
3/3
post-thumbnail

CSS: 경로를 따라 이동하는 애니메이션 만들기 🛣️ (offset-path, ray)

경로를 따라서 이동하는 애니메이션을 적용하려면 어떻게 해야할까요?🤔

예를 들어 원 요소가 별모양으로 움직여야 한다면⭐️? 경로를 따라서 움직이도록 로직을 작성하거나, keyframe에서 position값을 조정해서 작성할 수도 있습니다.

/* 실제로 적용 가능한 별모양 애니메이션입니다. */
@keyframes moveAlongStar {
  0% {
    left: 50%;
    top: 0%;
  }
  10% {
    left: 61%;
    top: 35%;
  }
  20% {
    left: 98%;
    top: 35%;
  }
  30% {
    left: 68%;
    top: 57%;
  }
  40% {
    left: 79%;
    top: 91%;
  }
  50% {
    left: 50%;
    top: 70%;
  }
  60% {
    left: 21%;
    top: 91%;
  }
  70% {
    left: 32%;
    top: 57%;
  }
  80% {
    left: 2%;
    top: 35%;
  }
  90% {
    left: 39%;
    top: 35%;
  }
  100% {
    left: 50%;
    top: 0%;
  }
}

물론 이해가 쉽고 약간의 노력으로 간편하게 만들 수 있지만, 만약 별 모양을 수정해야 할 경우, 또는 별이 아니라 다른 모양으로 변경될 경우에는 위치값을 전부 수정해야 하지 않을까요?

🤔 { 별 끝부분이 좀 더 뾰족했으면 좋겠어요! )
😀 { 화이트 데이에는 하트 모양으로 바꿔봐요. )
😃 { 이번에는 크리스마스 트리는 어떤가요? )

오늘은 이런 경우에 사용할 수 있는 offset-path에 대해 알아보려 합니다.


offset-path

MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/offset-path
https://developer.mozilla.org/en-US/docs/Web/CSS/ray

offset-path 속성은 요소가 따라 이동할 경로를 정의하는 CSS 속성입니다. 지정된 경로를 움직이게 할 수 있는데, 이 경로는 참조하고 있는 position 요소의 박스이거나, circle, ellipse, polygon과 같은 기본 도형일 수 있고, url의 svg이거나, ray 함수일 수 있습니다. 이를 속성의 값으로 입력하면 됩니다.

추가로 알고 있어야할 속성은 아래 세 가지입니다.

이해를 돕기 위해 MDN 문서를 기반으로 노란 박스가 움직이는 예제를 만들었습니다.

  • 모든 노란 박스는 offset-distance 0%에서 100%으로 애니메이션을 적용했습니다.
  • offset-distance 0%일 때 투명도는 20%, 100%일 때 100%입니다.

1. 박스 모델의 엣지와 도형을 활용한 경로 지정

첫 번째 예시입니다.

  • 0-a의 offset path는 padding-box 입니다. 패딩을 포함한 영역을 경로로 움직입니다.
  • 0-b의 offset path는 content-box 입니다. 이는 패딩을 제외한 컨텐츠 영역을 경로로 삼아 움직입니다.
  • 0-c는 CSS 기본 모양 함수인 polygon 함수를 사용하여 경로를 그렸습니다.

이렇게 참조하고 있는 position 요소의 박스를 따라 움직이는 애니메이션을 만들 수 있습니다. 설정한 animation-duration인 5초에 맞춰 움직이기 위해 박스의 속도가 다른 것을 볼 수 있죠. 저는 박스에 공통적인 애니메이션을 적용했는데, 참고 MDN 예제처럼 세부 조절을 하면 자연스러워 보일 것 같습니다.

자세한 박스 모델의 유형 설명은 MDN 문서를 참고해주세요: https://developer.mozilla.org/en-US/docs/Web/CSS/box-edge

2. SVG를 사용한 경로 지정

두 번째 예시에서 박스들은 url에 쓰여진 id의 SVG의 선을 따라서 움직입니다.

  • 1-a는 사각형 path를 따라 움직입니다.
  • 1-b는 별 path를 따라 움직입니다.

만약 요소의 애니메이션이 복잡해서 keyframe으로 조절하기 애매하다면, SVG를 사용하여 path에 따라 움직이는 애니메이션을 구현할 수 있습니다.

3. ray() 함수를 사용한 경로 지정

세 번째, 네 번째 예시에서는 ray 함수를 사용했습니다.

ray 함수의 오리진은 50%, 50%입니다. angle은 시작 위치부터 시작되는 path가 어떤 각도로 이동할지 결정합니다. 0도는 y축이 올라가는 방향이며, 시계 방향으로 각도가 증가합니다.(원뿔 그라데이션 conic-gradient와 동일합니다.) 또한 요소가 해당 라인을 top으로 맞닿도록 회전이 되어있는 모습을 볼 수 있습니다.

  • 2는 0deg 방향으로 움직이며, 박스를 벗어나지 않습니다.
  • 2는 0deg 라인을 top으로 향하도록 회전되어 있습니다.(offset-rotate 속성의 기본값 auto 동작입니다.)

네 번째 예시에서 박스는 영역의 왼쪽 위에서 오른쪽 아래로 대각선 이동합니다. offset-rotate을 0deg로 설정해 요소가 회전하지 않도록 했습니다. at 0px 0px은 시작 위치를 결정합니다. farthest-corner는 시작 위치에서 가장 멀리 있는 코너를 타겟으로 합니다. 함수에 입력하는 옵션의 순서는 중요하지 않습니다.

  • 3은 offset-position 0px, 0px에서 farthest-corner로 이동합니다.
  • 3은 offset-rotate는 0deg로, 요소가 회전하지 않았습니다.

전체 예제 코드는 아래 링크에서 확인할 수 있습니다.
https://dusunax.github.io/javascript/css/offset-path.html


결론

앞서 말씀드렸던 문제상황을 가장 쉽게 해결하는 방법은, 경로로 사용할 SVG 파일을 피그마와 같은 그래픽 툴을 통해 만들고, 매 UI 변경시에 갈아끼우는 것입니다.

특정 영역 내에서만 애니메이션을 동작하게 하거나, 특정 경로를 따라 움직이도록 구현하려면 보통 JavaScript를 사용해 요소의 clientWidth, clientHeight를 확인하거나, 로직으로 position 속성을 조정하는 방식으로 해결해야 합니다. 하지만 HTML5와 CSS3만으로도 이를 간단하게 구현할 수 있다는 점을 확인해 봤습니다.

코드를 작성하다보면 JavasScript단에서 해결하지 않아도 되는 문제들이 있습니다. 예를 들어, 가상 선택자를 사용한 스타일링, 다양한 input의 속성들 (예를 들어 file의 mimetype과 multiple 지정), 여러 문단의 텍스트를 나누어 출력할 때 column-fill: balance 같은 CSS 속성을 잘 활용하면, 자칫 JavaScript로 풀려고 시도할 문제들을 추가 코드 없이 해결할 수 있습니다.

이처럼 마크업과 스타일만으로도 해결할 수 있는 문제들이 많으며, 때로는 이 방식이 가장 적합할 때도 있습니다. 게다가 CSS는 계속해서 발전하고 있어, 새로운 기능들이 꾸준히 추가되고 있습니다.

심심하다면 재미로 JavaScript 없이 다양한 기능을 구현할 수 있습니다.

  • input과 datalist를 활용한 자동완성 검색창
  • 라디오 버튼과 nth-child 선택자를 이용한 슬라이드
  • label과 체크박스로 만드는 모달
profile
안녕하세요.

0개의 댓글