Progress Bar를 Animation으로 구현해보기
css를 입사해서 주먹구구식으로 급하게 독학하다보니 애니메이션 쪽에서는 완전 잼병이다…🤭 그래서 이번 기회에 확실히 짚고 넘어가려고 한다.
CSS - 애니메이션
-
@keyframes [Animation Name] {}
✓ 개발자가 애니메이션 중간중간의 특정 지점들을 거칠 수 있는 키프레임들을 설정함으로써 CSS 애니메이션 과정의 중간 절차를 제어할 수 있게 한다.
-
animation
✓ 다수의 스타일을 전환하는 애니메이션을 적용한다.
-
transform
✓ 요소에 회전, 크기 조절, 기울이기, 이동 효과를 부여할 수 있다.
-
transition
✓ 엘리먼트 두 가지 상태 사이에 변화를 줄 수 있다.
더 많은 속성들이 있겠지만, 우선 업무가 급하기 때문에 딱 필요한 것들만 간단히 공부하고 바로 구현에 들어갔다.
구현하려는 것
구현하려는 Progress Bar는 아래 그림과 같은 타임라인 형식이다.
일단 감이 안잡혀서 코드펜이나 코드샌드박스에서 서치해봤는데 비슷한 것 조차도 나오지 않았다… 나오더라도 유저가 액션을 취해야 다음으로 넘어가는 타임라인 애니메이션만 존재했다.
코드
정말 모르겠다 싶어서 일단 단순 progress bar부터 구현했다. (vue3 script setup 버전으로 구현했다.)
<!-- HTML 코드 -->
<div class="progress">
<div class="progress-bar__container">
<div class="progress-bar"></div>
</div>
</div>
// css 코드 (scss)
.progress {
display: absolute;
top: 100px;
height: 100%;
margin-left: 30px;
&-bar {
position: absolute;
width: 100%;
height: 100%;
content: '';
background-color: #182650;
&__container {
top: 30px;
width: 12px;
height: 270px;
border-radius: 2rem;
position: relative;
overflow: hidden;
transition: all 0.5s;
will-change: transform;
box-shadow: 0 0 5px #e1ffb1;
background-color: #ffffff;
}
}
}
// script 코드
onMounted(() => {
const progressBar = document.querySelector('.progress-bar');
const progressBarStates = [0, 25, 50, 75, 100];
// const progressBarStates = [100, 95, 80, 68, 34, 27, 7, 0];
let time = 0;
let endState = 100;
progressBarStates.forEach((state) => {
let randomTime = Math.floor(Math.random() * 3000);
setTimeout(() => {
if (state == endState) {
gsap.to(progressBar, {
y: `${state}%`,
duration: 2,
backgroundColor: '#000000',
});
} else {
gsap.to(progressBar, {
y: `${state}%`,
duration: 2,
});
}
}, randomTime + time);
time += randomTime;
});
});
})
순수 css로 구현하는 것보다 gsap과 같은 좋은 css 라이브러리가 있기 때문에 gsap을 사용했다. 정말 항상 느끼지만 이런 라이브러리 만든 사람들은 상받아야 한다… (이미 받았나?)
✓ setTimeout을 통해 초당 진행률을 쉽게 구현할 수 있었다.
어쨌든 위와 같이 구현하면 아래와 같은 결과물이 나온다.
→ 캡쳐본이지만 애니메이션이 잘 구현된다. 하얀색이 점차 내려오는 형태의 bar progress가 구현됐다.
👉🏻 곧 이어서 타임라인을 위한 circle progress animation도 구현해볼 예정이다. 사실 지금 하고 있는데 생각보단 진전이 좋다. 아직 완성률은 30%이다…😭