스크롤 되면 현재 위치를 계속 보여준다.
< 스크롤 되면 현재 위치를 계속 보여준다. >

Scrollbar & Progress Indicator

본문의 내용이 긴 경우에 사용자에게 현재 어느정도 읽었는지 알려주면, 사용자에게 보다 많은 정보를 내어주게 되는 것이며 이는 곳 사용자 스스로 통제권을 더 가지고 있다고 느껴지게 만듭니다. 긴 글은 사용자가 의도적으로 집중하면서 읽어야하기 때문에 이는 더욱 중요한 요소라고 할 수 있습니다.

요소를 표시하는데에 있어서 조심하여야할 점은, 본문의 읽기 흐름을 방해하지 않으면서 표시되도록 하는 것입니다. 아마도 가장 적절한 위치는 최상단에 가는 막대기 형태로 나타나는 것이 좋을 것 같습니다(사실 이거 쓰는 웹페이지들이 다 이런 형태로..).

요즘에는 컨텐츠 페이지 자체도 무한스크롤 형태로 제공되는 곳이 많이 있기 때문에 스크롤바만을 가지고 현재 읽기의 진행상태를 파악하기는 힘듭니다. 임의적으로 각 아티클별로 측정을 해야하는 상황이므로, progress indicator의 중요성은 더 커졌다고 할 수 있습니다(하지만 일단 저희가 쓰려고 만드는 것이기에 여기에서는 단일 페이지 단일 아티클로만 가정합니다).

Implementation

원리는 간단합니다. 우리에게는 페이지 전체의 길이를 알 수 있고, 윈도우의 크기도 알 수 있으니 대충 그것들을 짜집기하면 될 것 같습니다. 그런데 단순하게 그냥 스크롤위치와 문서길이만 가지고 계산하면 끝에 갔을 때 100%가 안되거나, 반대로 끝까지 내렸을 때 100%로 맞추면 시작할 때 0%가 아니라 화면크기만큼 x%가 진행되어버립니다.

계산되는 ScrollTop과 우리가 기대하는 진행률
< 계산되는 ScrollTop과 우리가 기대하는 진행률 >

위를 계산하기 위해서는 왠지 윈도우 비중과 전체 페이지의 비중 막 이래저래 섞어야할 것 같은데, 아래와 같이 단순하게 풀 수도 있습니다. 그냥 전체 페이지길이에서 윈도우 높이를 빼고나서 windowScrollTop만 가지고 구하면 실제 우리가 생각하는 퍼센테이지와 일치하게 됩니다.

우리가 기대하는 진행률을 구하기 위한 방법
< 우리가 기대하는 진행률을 구하기 위한 방법 >

위 사칙연산 코드는 아래와 같습니다. 현재 페이지의 진행률이므로 이걸 응용하면 무한스크롤로 응용할 수도 있습니다.

$(window).on('scroll', function(){
    var currentPercentage = ($(window).scrollTop() / ($(document).outerHeight() - $(window).height())) * 100;
}).

퍼센테이지를 구했으므로 마크업과 CSS를 구성하면 됩니다. 일단 DOM은 색깔과 길이가 있는 단 하나의 div만 있어도 될 것 같습니다.

var progressIndicator = '<div id="i-am-progress-indicator" style="position:fixed;top:0;height:5px;background:blue;width:'+currentPercentage+'%;"></div>';

이정도까지가 단순하게 구현원리에 해당됩니다. 아래는 실제 구현이 된 상태입니다.

JS Bin on jsbin.com

Optimization

성능상 위와 같이 하는 경우에는 스크롤시마다 엄청 잦은 DOM 수정이 발생할 것이므로, 최적화를 위하여 transform을 이용하여 수시로 빡센 랜더링이 발생하지 않도록 처리를 합니다. 그리고 미세하기는 하지만 움직임이 다소 딱딱하므로 easing도 추가합니다. 따라서 진행률의 폭을 전체로 맞추고 좌측으로 -100% 밀어버린 후에 조금씩 오른쪽으로 빼는 방식을 취합니다.

왼쪽보다는 오른쪽 방법이 훨씬 성능 이득이 있습니다
< 왼쪽보다는 오른쪽 방법이 훨씬 성능 이득이 있습니다 >

var progressIndicator = '<div id="i-am-progress-indicator" style="width:100%;transition:transform 0.3s ease-out;transform:translate3d(-'+(100-currentPercentage)+'%, 0, 0);"></div>';

아래는 위와 같은 기능들을 더 달고, 아예 퍼센테이지까지 옵션으로 추가한 버전입니다.

왼쪽에 위치한 것은 보질 못했지만 이것도 꽤 괜찮습니다.

jQuery Plugin

여기에서 삽질한 것들을 모아서 다른분들의 삽질을 막기 위하여, jQuery 플러그인으로 만들었습니다. 기왕 손 댄김에 사용하기 편리하도록 옵션과 이벤트 커스텀까지 넣어서 간단한 플러그인으로 제작을 해보았습니다. 저희가 사용하면서 필요한 부분이 있다면 계속 기능을 추가할 예정입니다.

Usage

<script src="https://cdn.rawgit.com/tyleteam/jquery-progress-indicator/master/jquery-progress-indicator-1.0.5.min.js"></script>

<script>
    $.progressIndicator();
</script>

Options & Events

$.progressIndicator({
    direction : 'top',
    barColor: 'rgb(253, 191, 38)',
    percentageEnabled : true,
    percentageColor: '#222',
    easingSpeed : 0.5,
    height: 4,
    target : 'body',
    onStart : function(){
        console.log("onStart");
    },
    onEnd : function(){
        console.log("onEnd");
    },
    onProgress : function(perecent){
        console.log(perecent);
    }
});

Supports

귀찮아서 아직 브라우저 테스트는 해보지 않았습니다만, IE Edge 를 포함한 모든 모던웹 브라우저에서는 작동하지 않을까 생각합니다.

Github Repository : https://github.com/tyleteam/jquery-progress-indicator


참고할만한 문서