본문 바로가기

업무이야기

자바스크립트 부드럽게 느려지는 애니메이션 - progress bar

이번에 인프런 애플사이트를 클론하는 코딩 수업을 들으면서 다양하게 활용 가능할것 같은 애니메이션이 있어 한번 정리해두려고 합니다. 애플 사이트는 스크롤 하면서 동영상 사진이나 글자의 효과 또는 위치를 움직이는 효과를 넣어주었는데요. 이것은 기본적으로 화면을 스크롤 가능하도록 스타일로 화면의 높이를 강제적으로(?) 늘려주고 스크롤값에 따라 여러 효과들을 넣어주는 원리입니다.

 

여기에 동영상을 처리하여 (프레임을 이미지화) 멋진 효과들을 입히는데요, 조금 더 페이지를 고급화 시키기 위해서 부드러운 감속 효과를 넣어주면 한층 더 있어보이는 느낌이 뿜뿜하게 됩니다.

 

먼저 아래와 같이 기본 마크업 + 스타일 + 스크립트를 입혀보았습니다.

 

 

기본 스타일 적용

 

마크업 해놓은 박스를 스타일에서 fixed 로 고정시켜두고 스크립트에서 pageYOffset 을 사용해서 스크롤될때마다 길어지는 프로그래스바 같은 애니메이션을 구현했습니다. 

 

마크업 ▼

1
<div class="box"></div>
cs

 

CSS 화면을 500vh로 늘려줌/ position은 고정 fixed

1
2
3
4
5
6
7
8
9
10
11
12
13
body {
  height: 500vh;
  margin: 0;
  padding: 0;
}
 
.box {
  position: fixed;
  top: 100px;
  width: 0;
  height: 50px;
  background-color: blueviolet;
}
cs

 

Javascript

1
2
3
4
5
6
7
8
9
10
11
const box = document.querySelector('.box');
let yOffset = 0;
 
window.addEventListener('scroll', ()=>{
  let yOffset = window.pageYOffset;
 
  console.log(yOffset)
  box.style.width = `${yOffset}px`
})
cs

 

애니메이션을 보면 터덕 터덕 소리가 나는것처럼 끊어져서 움직이는걸 확인할 수 있는데요. 여기에 감속 효과를 적용해 보도록 하겠습니다.

 

 

감속효과가 적용된 애니메이션

 

 

CSS 파일은 그대로고 javascript를 수정 적용한 화면입니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const box = document.querySelector('.box');
const acc = 0.1;
let yOffset = 0;
let delayYOffset = 0;
let roofState = true;
 
window.addEventListener('scroll', ()=>{
});
 
loop = () => {
  let yOffset = window.pageYOffset;
 
  box.style.width = `${delayYOffset}px`
  delayYOffset = delayYOffset + (yOffset - delayYOffset) * acc;
  console.log(loop);
 
  if(delayYOffset < 1) {
    cancelAnimationFrame(loop);
    roofState = false;
  }
 
  requestAnimationFrame(loop);
}
 
loop();
cs

* requestAnimationFrame(loop); : 'requestAnimationFrame()' 함수로 이벤트 scroll() 과 같은 기능을 구현해줍니다.

* delayYOffset = delayYOffset + ( YOffset - delayYOffset ) * acc  이부분이 감속의 원리가 적용된 식입니다.  acc의 0.1이 계속 곱해지면서 값이 줄어들며 점점 느려지게 됩니다.

* 위 코드에서 보완할 점은 loop가 계속 돌아가고 있다는 점입니다. console 창을 보시면 loop 함수가 계속 돌아가고 있습니다. 이 점을 보완하기 위해 아래와 같은 코드를 추가해 줍니다.

 

 

완성

 

최종 자바스크립트 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const box = document.querySelector('.box');
const acc = 0.1;
let yOffset = 0;
let delayYOffset = 0;
let roofState;
let roofId;
 
window.addEventListener('scroll', ()=>{
  if(!roofState) {
    requestAnimationFrame(loop);
    roofState = true;
  }
});
 
loop = () => {
  let yOffset = window.pageYOffset;
 
  box.style.width = `${delayYOffset}px`
  delayYOffset = delayYOffset + (yOffset - delayYOffset) * acc;
  console.log(loop);
 
  roofId = requestAnimationFrame(loop);
 
  if(Math.abs(yOffset - delayYOffset) < 1) {
    cancelAnimationFrame(roofId);
    roofState = false;
  }
}
 
loop();
cs

* Math.abs 는 절대값을 만들어주는 함수입니다. 

* YOffset - delayYOffset 오차범위가 1px 미만일 때 애니메이션을 멈춰줍니다. (loop를 중단합니다.)

* Scroll 할 때 loop가 돌고 있지 않다면 loop함수가 실행되도록 해줍니다. 

 

animation.html
0.00MB

 

반응형