본문 바로가기

Web Development/Javascript

[Vanilla JS]window.innerHeight를 사용한 스크롤 애니메이션 구현

스크롤 애니메이션은 스크롤을 내릴때 애니메이션이 발동되는 참 잘쓰면 좋은 효과이다. 현재 제작중인 포트폴리오 웹사이트에서 스크롤 애니메이션을 사용하기 위해 한번 공부해봤다. 그 이전에 자바스크립트로 스크롤 애니메이션을 사용하기 위해서는 먼저 window, viewport, 그리고 요소의 크기에 대한 개념을 잡고 시작하는게 좋다.

1. window와 viewport

1) window

HTML에서 윈도우란 브라우저 자체를 뜻한다. 말로 설명하면 어려울 수도 있으니 그림으로 표현하자면 다음과 같다.

viewport 와 window

window의 경우에는 브라우저 자체를 뜻한다. 자바스크립트에서 윈도우의 크기를 구하는 함수로는 다음의 것들이 있다.

window.innerHeight //네비게이션 창을 제외한 높이  
window.innerWidth  
window.outerHeight //브라우저 자체의 높이  
window.outerWidth //브라우저 자체의 너비window.screen.height  
window.screen.widthdocument.documentElement.clientWidth //뷰포트 너비  
document.documentElement.clientHeight //뷰포트 높이function activateString(){  
   //get string element  
   const words \= document.querySelector('.string')  
​  
   //get window height  
   var windowHeight \= window.innerHeight / 1.2;  
   var elementHeight \= words.getBoundingClientRect().top;  
​  
   //check windowHeight reaches element Height  
   if (elementHeight < windowHeight){  
       words.classList.add('string-active')  
  } 
}

이외의 화면 전체의 크기를 구할수도 있다.

window.screen.height
window.screen.width

2) viewport

Viewport는 화면이 출력되는 공간을 의미한다. 사진에서와 같이 우리가 인터넷으로 보는 내용들이 viewport에 출력되는 것이다. 그렇다면 document.innerHeight, outerHeight이 viewport와 같은 것이 아닌가 헷갈릴수도 있는데 MDN문서에 따르면 viewport의 경우는 스크롤바를 제외한 크기이고 document의 경우에는 스크롤바까지 포함한 길이라고 한다.

Viewport의 크기를 구하기 위한 함수는 다음과 같다.

document.documentElement.clientWidth //뷰포트 너비
document.documentElement.clientHeight //뷰포트 높이

2. 요소(Element)의 위치

요소의 위치는 좌측 상단인 픽셀의 시작지점(0,0)에서부터 측정이 된다. 다음의 그림과 같이 요소의 위치를 파악한다면 쉬울 것 같다.

요소(Element)의 document 안에서의 위치

(출처: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)

요소의 위치를 파악하는 자바스크립트 함수로는 getBoundingClienRect() 가 있다. 해당 함수를 사용하면 읽기 전용의 top,right,bottom,x,y,width,height 속성을 리턴받는데 필요한 속성들을 사용하면 될 것같다.

3.스크롤 애니메이션 구현하기

해외 유튜버 Dev Ed 님의 영상을 참고하여 스크롤 애니메이션 구현하는것을 학습해봤다. 여기서는 window의 innerHeight와 애니메이션을 구현할 엘리먼트의 위치값 중 상단(top) 값을 이용해 서로를 비교하는 방식으로 구현했다.

동영상 링크: https://www.youtube.com/watch?v=C_JKlr4WKKs

[scroll.js]

function activateString(){
    //get string element
    const words = document.querySelector('.string')

    //get window height
    var windowHeight = window.innerHeight / 1.2;
    var elementHeight = words.getBoundingClientRect().top;

    //check windowHeight reaches element Height
    if (elementHeight < windowHeight){
        words.classList.add('string-active')
    }

}

function toBottom(){
    var bottomHeight = document.querySelector('.bottom').getBoundingClientRect().top;
    window.scrollTo(0, bottomHeight)
    console.log("bottom" + bottomHeight)
}

window.addEventListener('scroll', activateString)
document.querySelector('.nav-to-bottom').addEventListener('click', toBottom)

[scroll.css]

.empty{
  width: 100%;
  height: 2000px;
  background-color:pink;
}

.bottom{
  width: 100%;
  height: 2000px;
  background-color:pink;
}

.string{
  font-size: 40px;
  opacity: 0;
  transform: translateX(40px);
  transition: 1s;
}

.string-active{
  opacity: 1;
  transform: translateX(0px);
}

[index.html]

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="scroll.css">
  <title>Scroll Test</title>
</head>
<body>
  <button class="nav-to-bottom">to Bottom</button>
  <div class="empty">
    empty box for spacing
  </div>
  <div class="string">String to be appear</div>
  <div class="bottom">
    empty box for spacing
  </div>
  <script src="scroll.js"></script>
</body>
</html>

해당 코드를 설명하자면 스크롤 애니메이션이 발동되는 핵심은 애니메이션이 담긴 요소의 위치와 윈도우의 innerHeight이다. 윈도우의 innerHeight은 고정되어있고 스크롤을 내려도 변경되지 않는다. 하지만 요소는 스크롤을 할 때마다 변경된다. 특히 여기서는 요소의 top 값을 사용했는데 그 이유는 getBoundingClientRect 함수의 경우 문서 내에서 요소의 절대위치를 가져오기 때문이다.

따라서 스크롤을 하면서 요소에 더 가까워질수록 top의 값은 더 작아지고 요소가 브라우저 안에 나타나는 순간에는 innerHeight의 값보다 줄어든다. 그 이유는 다음의 그림을 보면 이해하기가 쉽다.

스크롤 애니메이션 작동원리 이해

스크롤을 내리다 보면 요소가 하단에 나타날 때 top의 값이 innerHeight보다 작아진다. 이 순간에 스크립트 파일의 정의된 toBottom 함수가 작동된다. 물론 지속적으로 요소를 추적하기 위해서는 window에 스크롤 이벤트를 적용해줘서 스크롤을 할 때마다 toBottom 함수를 실행시킨다.(그렇지 않으면 최초 스크롤때만 toBottom 함수가 실행되고 끝난다.)

지금까지 innerHeight와 getClientBoundRect() 함수의 top 값을 이용하여 스크롤 애니메이션을 동작하는 방법에 대해 알아봤다. 스크롤 애니메이션을 사용한다면 생각보다 멋져보이는 웹사이트를 디자인 할 수 있기 때문에 사용하면 좋을 것 같다. 이 글에서 소개한 방법 이외에도 innerHeight 대신 window.pageYoffset 을 사용하여 얼마나 문서가 스크롤됬는지 파악하고 이를 이용하여 스크롤 애니메이션을 구현하는 방법도 있다. 다음에 한번 적용해보고 어떠한 방법이 좋을지 판단해봐야겠다.

추가적으로 인피니티 스크롤로 이루어진 페이지에서 중요한 해당 요소의 위치로 이동하는 기능도 구현되어있으나 이에 관련된 자세한 내용은 나중에 다시 포스팅해서 올리겠습니다.

*글에 틀린 부분이 상당히 존재할 수도 있습니다. 피드백은 언제나 환영이므로 틀린 부분이 있다면 피드백 부탁드립니다.