기본적인 원리는 자바스크립트: 무한 스크롤 (스크롤 이벤트 이용, 라이브러리 없이) 이 글에 나온 것과 동일합니다.

스크롤 인디케이터(스크롤 상태 표시기)란 스크롤을 할 때 현재 스크롤된 영역이 전체 컨텐츠 영역의 몇 % 진행되었는가를 나타내는 표식입니다. 아래 그림에서 파란색 선이 스크롤 인디케이터입니다.

스크롤 인디케이터는 스크롤 정보를 얻어와 구현합니다. 스크롤 이벤트를 하면 이벤트 타겟에 scrollingElement라는 프로퍼티가 있는데 이것을 통해 현재 스크롤 상태와 관련된 정보를 얻을 수 있습니다.

또는 document,documentElement || document.body 에서도 가져올 수 있습니다.

 

먼저 HTML 을 작성합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Scroll Indicator</title>
    <style>
        
        body {
            margin: 0px;
        }
        
        .header {
            display: flex;
            flex-direction: column;
            justify-content: center;
            position: fixed;
            width: 100%;
            text-align: center;
            border-bottom: 1px solid gray;
            background-color: whitesmoke;
        }
        
        #scroll-indicator {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 4px;
            background-color: lightblue;
            transform: translateX(-100%);
        }
        
        #contents {
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="header">
        <h2>Lorem Ipsum</h2>
        <div id="scroll-indicator"></div>
    </div>
    <div id="contents"></div>
    <script>
        
        // ..... //

    </script>
</body>
</html>

transform: translateX(-100%); – 이 부분이 스크롤 인디케이터가 보여지는 데에 핵심 역할을 합니다. 처음에는 왼쪽으로 100% 이동한 상태이기 때문에 보이지 않습니다. 그러다가 스크롤이 진행될수록 translateX의 퍼센트 수치가 -100%에서  0%에 가까워지면서 스크롤 인디케이터의 파란색 부분이 표시가 됩니다.

 

다음 자바스크립트 부분을 구현합니다.

const scrollIndicator = document.getElementById("scroll-indicator")
const contents = document.getElementById("contents")

fetch("https://baconipsum.com/api/?type=all-meat&paras=50&format=html")
    .then(response => response.text())
    .then(result => contents.innerHTML = result)
    
window.addEventListener("scroll", e => {
    // clientHeight : 웹 브라우저 창의 높이
    // scrollTop : 현재 스크롤된 부분의 맨 위의 높이
    // scrollHeight : 문서의 총 높이 (= 스크롤의 총 높이)
    // contentHeight : 전체 총 높이에서 클라이언트 높이를 뺀 것
    
    const { scrollTop, scrollHeight, clientHeight } = e.target.scrollingElement
    const contentHeight = scrollHeight - clientHeight
    const percentage = (scrollTop / contentHeight) * 100
    
    scrollIndicator.style.transform = `translateX(-${100 - percentage}%)`   // -100% ~ 0%
    scrollIndicator.style.transition = `transform 0.5 ease-out` // 부드러운 애니메이션
})
  • clientHeight : 웹 브라우저 창(내용이 보여지는 영역)의 높이입니다.
  • scrollTop : 현재 스크롤된 부분의 맨 위의 높이입니다. (=현재 스크롤의 위치) 스크롤을 하지 않았다면 0이고. 스크롤을 할 때마다 값이 증가합니다.
  • scrollHeight : 문서의 총 높이 (= 스크롤 대상의 총 높이) 입니다.

 

다음 contentHeight라는 변수를 생성합니다. 최초 스크롤되지 않은 상태에서는 스크롤 진행 상황이 0%이어야 합니다. 그런데 clientHeight가 포함된 총 높이에서는 스크롤되지 않고 진행률에 포함하지 않아야 할 clientHeight 만큼의 높이가 쌓여있기 때문에 이 높이만큼을 제외해야 하는 것입니다. 스크롤이 끝까지 진행되었다면 contentHeightscrollTop의 수치는 같아집니다.

(scrollTop / contentHeight) * 100 의 공식을 통해 진행률(percentage)를 구하고, transform(translateX(**%))를 통해 진행률에 따라 스크롤 인디케이터의 색깔 막대를 움직이면서 진행 상황을 표시합니다. 그리고 선택 사항으로 부드러운 전환 효과를 위해 transition 을 추가합니다.

 


문의 | 코멘트 또는 yoonbumtae@gmail.com  donaricano-btn

카테고리: WEB: Frontend

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다