SVG를 활용한 텍스트 애니메이션 구현하기 (기초편)
일러스트 제작 후 SVG 파일로 변환해서 웹에서 사용한 적은 많지만 변환된 SVG 태그로 애니메이션을 줄 생각은 못한 사람, 저요🤔
이번 기회에 path를 이용한 간단한 애니메이션을 접해보자.
우선 SVG 애니메이션에 사용되는 stroke-dasharray와 stroke-dashoffset 에 대해 알아야한다.
두 속성은 선에 대한 스타일 속성으로 선의 그림을 제어하는 데 사용된다.
stroke-dasharray
stroke-dasharray 속성은 선의 모양을 정의하는 데 사용되며,
ex) stroke-dasharray="4, 2"
속상 값으로는 각각 선의 길이와 비율을 나타낸다.
4픽셀 직선과 2픽셀 간격으로 구성된 선을 생성하여
'ㅡ ㅡ ㅡ ㅡ ㅡ ㅡ ㅡ ㅡ' 이런식으로 선이 생성된다.
값을 동일하게 준다면 점선으로 보이게 된다.
만약 path의 길이가 100px이면서 간격도 100px로 준다면,
'ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ' 이처럼 선은 직선으로 이어진 것처럼 보이게 된다.
물론 100px의 간격도 잘려있긴하지만 적용되어 있다.
|'ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ'|(이 뒤로 간격 존재)ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
stroke-dashoffset
stroke-dashoffset 속성은 선의 시작점에서 경로의 어느 지점에서 그리기 시작할지를 지정하며, stroke-dasharray 값에 영향을 준다.
stroke-dashoffset 값이 클수록 선이 그려지는 지점이 이동하고, 작을수록 선이 그려지는 지점이 원래 위치에 가까워진다.
ex) stroke-dashoffset="20"
시작점에서 20픽셀 이후부터 그려지기 시작한다.
설명하자면 이런식👇
<원래 path의 길이 100px>
'ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ'
<20px 이후부터 path 그려짐>
' ㅡㅡㅡㅡㅡㅡㅡㅡ'
path의 길이를 기준으로 두 속성의 값이 정해지는데 보통 path의 가장 작은 크기는 0, 큰 크기는 1000으로 한다.
이를 통해 간단한 애니메이션을 줘보자.
우선, 일러스트레이터로 'coding'이라는 텍스트를 svg코드로 변환해 가져온다.
<svg id="레이어_1" data-name="레이어 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 213.81 99.42">
<g class="cls-2">
<path d="M7.36,16.62a5.51,5.51,0,0,0,4-3l.14.07A5.81,5.81,0,0,1,6.57,17C3.33,17.2.1,15.45,0,11.58-.11,7.52,3.57,5.63,6.14,5.63a11,11,0,0,1,4.43,1.24l-.35,1.94h-.14c-.56-1.4-2.79-3.42-5-2.9-2.88.65-3.94,4.36-2.95,7.17A4.89,4.89,0,0,0,7.36,16.62Z" transform="translate(101.17)"/>
<path d="M25.08,10.83A6.3,6.3,0,0,1,18.73,17c-3.16,0-5.86-1.92-5.86-5.2a6.22,6.22,0,0,1,6.35-6.21C22.36,5.63,25.08,7.59,25.08,10.83Zm-2-.75c-.82-2.81-3-4.81-5.69-4s-3.4,3.7-2.58,6.54,3,4.82,5.7,4S23.93,12.91,23.11,10.08Z" transform="translate(101.17)"/>
<path d="M38.37,16.9H36V10.62C35.56,13.34,34.37,17,31.09,17a4.59,4.59,0,0,1-4.34-4.64C26.61,6.61,32,5.63,34.6,5.63A4.87,4.87,0,0,1,36,5.84v-4c0-.82-.07-1-.54-1.12V.49L37.7,0h.16V15.35c0,.82.16,1.17.51,1.38ZM36,9.23V6a5.4,5.4,0,0,0-1.41-.21c-2.27,0-6.35,1-6,7,.12,2,1.54,4.24,3.56,3.87C34.77,16.1,36,11.2,36,9.23Z" transform="translate(101.17)"/>
<path d="M42.92,16.73v.17H40v-.17c.35-.21.51-.56.51-1.38V7.43c0-.82-.07-1-.51-1.13V6.14l2.2-.51h.17v9.72C42.39,16.17,42.55,16.52,42.92,16.73ZM40.3,2.63a1.1,1.1,0,1,1,1.1,1.1A1.11,1.11,0,0,1,40.3,2.63Z" transform="translate(101.17)"/>
<path d="M56.14,16.73v.17h-2.9v-.17c.37-.21.47-.6.4-1.38L53.1,9.4c-.17-1.76-1-3.75-3.05-3.35-2.63.51-3.12,5.41-3.12,7.38v1.92c0,.82.17,1.17.54,1.38v.17h-2.9v-.17c.35-.21.51-.56.51-1.38V7.43c0-.82-.07-1-.51-1.13V6.14l2.2-.51h.16v5.81c.31-2.63,1.1-5.81,4.15-5.81,1.92,0,3.56,1.31,3.84,4.12.24,2.27.47,4.73.57,5.6S55.79,16.52,56.14,16.73Z" transform="translate(101.17)"/>
<path d="M71.4,18.07c0,1.85-2.34,3.05-4.33,3.05A3.53,3.53,0,0,1,64,19.43a7.91,7.91,0,0,1-3.35,1.34c-1.25.09-2.18-.36-2.21-1.43,0-1.43,2.21-2.21,3.85-2.37-2.75-.33-5-2.16-5-5.13a6.24,6.24,0,0,1,6.37-6.21,6.89,6.89,0,0,1,2.63.51l4-1.17.14,1.17-3.78.16a4.9,4.9,0,0,1,2.86,4.53A6.31,6.31,0,0,1,63.18,17a1.1,1.1,0,0,1-.24,0c-1.54.07-3.35.61-3.23,2A1.25,1.25,0,0,0,61,20.37c1.2,0,2.56-.89,4.06-1.81,1.73-1,3.18-2.25,4.38-2.29A1.67,1.67,0,0,1,71.4,18.07ZM65,16.62c2.64-.78,3.39-3.71,2.57-6.54s-3-4.81-5.69-4-3.4,3.7-2.58,6.54S62.33,17.41,65,16.62Zm3.79.11a15.73,15.73,0,0,0-3.58,1.95l-1.06.63A3.26,3.26,0,0,0,67.07,21,2.53,2.53,0,0,0,70,18.47C70,17.39,69.74,16.59,68.8,16.73Z" transform="translate(101.17)"/>
</g>
</svg>
CSS의 keyframe을 사용하여 아래와 같이 애니메이션을 작성해봤다.
svg{
fill: none;
width: 500px;
stroke-width: 0.5px;
}
path{
stroke: #000;
stroke-dasharray: 1000; /* 전체 path 설정*/
stroke-dashoffset:1000; /* 현재 path 안보이는 상태 */
animation: path 10s forwards;
}
@keyframes path {
100%{ stroke-dashoffset: 0;} /* path 전체 보이게끔 */
}
결과는 아래와 같다.
(실제로는 더 느리지만 gif 따왔더니 살짝 빨라짐)
동시에 말고 좀 더 순차적으로 나타나게끔 하고싶어서 그 부분은 js를 사용해봤다.
const paths = document.querySelectorAll('path')
paths.forEach((path, i) => {
path.style.animationDelay = `${i / 4}s`
})
간단하지만 타이포그래피가 웹트렌드를 차지하는만큼 이런 svg애니메이션이 앞으로 자주 활용될 것으로 생각한다.
나중에는 스크롤 이벤트를 접목시켜 해봐도 좋을 듯 하다✍️