본문 바로가기

컴퓨터/프로젝트

무한 스크롤(Infinite Scrolling)

1. 소개

무한 스크롤이라는 주제로 사이트를 만들어볼 것이다. 말 그대로 계속해서 스크롤을 해야 하는 사이트이다. 깃허브에 있던 한 웹페이지를 보고 만들어보고 싶어서 만들어보았다.

참고한 사이트: vanillawebprojects.com/projects/infinite_scroll_blog/
참고한 깃허브: github.com/bradtraversy/vanillawebprojects/tree/master/infinite_scroll_blog

2. 구현 기능

  • 무작위 글 생성
  • 생성된 글 출력
  • 입력한 글 일치 여부 확인
  • 스크롤 인식
  • 맨 위로 올리는 버튼

이렇게 총 5가지 기능을 구현하였다.

3. 구현 방식

-무작위 글 생성

글 생성 방식은 Math.random을 이용하여 무작위 난수의 값을 받고 그것을 문자로 변환시켜주는 toString을 사용하여 변환시켜주었다.

let Random = Math.random().toString(36).slice(2);
let long_Random = Math.random().toString(36).slice(2);

위 코드에서 Random은 글 제목에 쓰일 문장이고 long_Random은 글 본문에 쓰일 내용이다. 그리고 반복문을 이용하여 글 내용의 길이를 조절하였고, 띄어쓰기 같은 경우에도 랜덤 값을 이용하여 50% 확률로 띄어쓰기가 되도록 하였다.

if(Math.floor(Math.random() * 10) % 2 == 0)
{
    long_Random += ' ';
}

아래 코드는 무작위 글 생성 과정을 담은 코드이다.

/* 무작위 글 생성 */
function lorem_ipsum(n) {
    let Random = Math.random().toString(36).slice(2);
    let long_Random = Math.random().toString(36).slice(2);

    /* 글 길이도 랜덤으로 글 내용 저장 */
    for (let i = 0; i < Math.random() * 100; i++) {
        if(Math.floor(Math.random() * 10) % 2 == 0)
        {
            long_Random += ' ';
        }
        long_Random += Math.random().toString(36).slice(2);
    }

    additional(Random, long_Random, n);
}

- 생성된 글 출력

참고 그림

위 참고 그림을 보면 main이라는 상자 안에 title과 content가 존재하는데 이러한 식으로 글 목록을 생성할 것이다. 그렇다면 main이라는 상자를 먼저 만들고 title과 content를 품으면 된다. title과 content를 사용할 때는 append를 사용하여 쉽게 추가할 수 있었고, appendchild를 이용하여 main의 자식으로 지정했다.

let main = document.createElement('div');
main.className = 'main';

let title = document.createElement('h3');
title.className = 'title';

let content = document.createElement('p');
content.className = 'content';

content.append(long_text);
title.append(text);

main.appendChild(title);
main.appendChild(content);

그리고 글 목록의 번호도 지정해야 하기 때문에 위와 같은 방식으로 숫자가 들어있는 상자를 만들어 main의 자식으로 지정한다.

let number = document.createElement('div');
number.className = 'number';

number.append(n);

main.appendChild(number);

아래의 코드는 생성된 글 출력의 과정을 담은 코드이다.

/* 해당하는 위치에 저장된 글들을 출력 */
function additional(text, long_text, n) {
    let number = document.createElement('div');
    number.className = 'number';

    let main = document.createElement('div');
    main.className = 'main';

    let title = document.createElement('h3');
    title.className = 'title';

    let content = document.createElement('p');
    content.className = 'content';

    number.append(n);
    content.append(long_text);
    title.append(text);

    main.appendChild(number);
    main.appendChild(title);
    main.appendChild(content);
    document.getElementById('container').appendChild(main);
}

- 입력한 글 일치 여부 확인

먼저 input 상자 안에 입력된 값과 main의 값을 받고 main의 길이만큼 반복하여 title과 content의 내용을 다른 변수로 전달받고 indexOf를 이용하여 일치 여부를 확인하고 title과 content 중 하나라도 일치하는 것이 있으면 출력을 하고 어느 것도 해당해되는 것이 없으면 글을 안 보이게 처리한다.

/* 입력한 값에 대한 글 제목 및 글 내용이 있는지 확인 */
function filter() {

    let value = document.getElementById("input").value;
    let main = document.getElementsByClassName('main');
    for (let i = 0; i < main.length; i++) {
        title = main[i].getElementsByClassName("title");
        content = main[i].getElementsByClassName("content");

        if (title[0].innerHTML.indexOf(value) == -1 && content[0].innerHTML.indexOf(value) == -1) {
            main[i].style.display = "none";
        }
        else {
            main[i].style.display = "block";
        }
    }
}

- 스크롤 인식

window.addEventListener을 이용하여 인식을 했는데 스크롤의 현재 위치, 화면에서 보이는 문서의 높이 그리고 문서의 전체 높이를 계산하여 맨 밑으로 가는 것을 인식할 수 있게 하고 로딩 화면을 보여주고 3000ms동안 기다리게 한다. 그리고 기다린 후에는 글을 추가시켜는 함수를 실행시킨다.

/* 스크롤바 위치 확인 및 로딩 실행 */
window.addEventListener('scroll', () => {
    let scrollLocation = document.documentElement.scrollTop;    //현재 스크롤 바 위치
    let windowHeight = window.innerHeight;                      //화면으로 보이는 스크린 화면의 높이
    let fullHeight = document.body.scrollHeight;                //웹 문서 중 body의 스크롤 높이

    /* 50은 웹페이지 margin 값 */
    if (scrollLocation + windowHeight >= fullHeight + 50) {
        let loading = document.getElementById('load');
        loading.style.display = "block";
        setTimeout(more, 3000);
    }
})

 

글을 추가하는 함수는 more인데 실행과 동시에 다시 로딩 화면을 안 보이게 한다.

let loading = document.getElementById('load');
loading.style.display = "none";

그리고 랜덤 값을 이용하여 글의 개수를 조절한다.

for (let i = 0; i < Math.random() * 70; i++) {
    lorem_ipsum(num++);
}

아래의 코드는 이 과정들을 담은 코드이다.

/* 스크롤바 위치 확인 및 로딩 실행 */
window.addEventListener('scroll', () => {
    let scrollLocation = document.documentElement.scrollTop;    //현재 스크롤 바 위치
    let windowHeight = window.innerHeight;                      //화면으로 보이는 스크린 화면의 높이
    let fullHeight = document.body.scrollHeight;                //웹 문서 중 body의 스크롤 높이

    /* 50은 웹페이지 margin 값 */
    if (scrollLocation + windowHeight >= fullHeight + 50) {
        let loading = document.getElementById('load');
        loading.style.display = "block";
        setTimeout(more, 3000);
    }
    scrollFunction();
})

/* 로딩 종료 및 글 목록 추가 */
function more() {
    let loading = document.getElementById('load');
    loading.style.display = "none";

    /* 무작위 갯수의 글 추가 */
    for (let i = 0; i < Math.random() * 70; i++) {
        lorem_ipsum(num++);
    }
}

-맨 위로 올리는 버튼

웹 페이지를 테스트하다가 계속해서 위로 올리는 게 번거로워서 한번 만들어보았다. 바로 전 스크롤 인식하는 함수에 scrollFunction이라는 함수가 있는데 버튼 보이게 하거나 안 보이게 하는 함수이다. 버튼이 맨 위에 있다면 보이게 하고 만약 조금이라도 스크롤 위치가 내려가 있다면 보이게 한다.

var btn = document.getElementById('btn');
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
    btn.style.display = "block";
} else {
    btn.style.display = "none";
}

그리고 클릭 이벤트로는 window.scrollTo를 이용하여 위치는 top: 0 즉, 맨 위로 이동시키고 behavior:'smooth' 이용하여 부드럽게 움직이게 하였다.

window.scrollTo({top:0, behavior:'smooth'});

아래의 코드는 이 과정들을 담은 것이다.

/* 버튼 보이는 이벤트 */
function scrollFunction() {
    var btn = document.getElementById('btn');
    if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
        btn.style.display = "block";
    } else {
        btn.style.display = "none";
    }
}

/* 부드럽게 위로 가기 */
function GoTop() {
    window.scrollTo({top:0, behavior:'smooth'});
}

4. 코드 및 구현

<!DOCTYPE html>
<html>
<head>
<title>Infinite Scrolling</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div class="top">
<h1>Infinite Scrolling</h1>
<input id="input" onkeyup="filter()">
</div>
<div id="container"></div>
<div id="load" class="fa fa-circle-o-notch fa-spin"></div>
<button id="btn" onClick="GoTop()">▲</button>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
body{
background-color: rgb(0, 183, 255);
color: white;
text-align: center;
}
input{
padding: 20px;
border-radius: 30px;
border: none;
font-size: 20px;
width: 80%;
}
.top{
margin-bottom: 50px;
}
.main{
word-break:break-all;
border: 2px solid;
margin-bottom: 50px;
margin-left: 20%;
width: 60%;
}
.title{
font-size: 25px;
}
.content{
font-size: 20px;
padding: 0px 20px 20px 20px;
margin: 0px;
text-align: left;
}
.number{
position: absolute;
background-color: white;
color:rgb(0, 183, 255);
padding: 10px;
font-size: 20px;
}
#load{
display: none;
font-size: 50px;
}
button{
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
border: none;
font-size: 20px;
padding: 15px;
background-color: white;
color: rgb(0, 183, 255);
cursor: pointer;
transition: 0.5s;
display: none;
}
button:hover{
background-color:rgb(0, 183, 255);
color: white;
border: 2px solid;
}
view raw style.css hosted with ❤ by GitHub
let num = 21;
/* 페이지 실행 시 글 목록 20개 생성 */
window.onload = function () {
for (let i = 0; i < 20; i++) {
lorem_ipsum(i + 1);
}
}
/* 무작위 글 생성 */
function lorem_ipsum(n) {
let Random = Math.random().toString(36).slice(2);
let long_Random = Math.random().toString(36).slice(2);
/* 글 길이도 랜덤으로 글 내용 저장 */
for (let i = 0; i < Math.random() * 100; i++) {
if(Math.floor(Math.random() * 10) % 2 == 0)
{
long_Random += ' ';
}
long_Random += Math.random().toString(36).slice(2);
}
additional(Random, long_Random, n);
}
/* 해당하는 위치에 저장된 글들을 출력 */
function additional(text, long_text, n) {
let number = document.createElement('div');
number.className = 'number';
let main = document.createElement('div');
main.className = 'main';
let title = document.createElement('h3');
title.className = 'title';
let content = document.createElement('p');
content.className = 'content';
number.append(n);
content.append(long_text);
title.append(text);
main.appendChild(number);
main.appendChild(title);
main.appendChild(content);
document.getElementById('container').appendChild(main);
}
/* 입력한 값에 대한 글 제목 및 글 내용이 있는지 확인 */
function filter() {
let value = document.getElementById("input").value;
let main = document.getElementsByClassName('main');
for (let i = 0; i < main.length; i++) {
title = main[i].getElementsByClassName("title");
content = main[i].getElementsByClassName("content");
if (title[0].innerHTML.indexOf(value) == -1 && content[0].innerHTML.indexOf(value) == -1) {
main[i].style.display = "none";
}
else {
main[i].style.display = "block";
}
}
}
/* 스크롤바 위치 확인 및 로딩 실행 */
window.addEventListener('scroll', () => {
let scrollLocation = document.documentElement.scrollTop; //현재 스크롤 바 위치
let windowHeight = window.innerHeight; //화면으로 보이는 스크린 화면의 높이
let fullHeight = document.body.scrollHeight; //웹 문서 중 body의 스크롤 높이
/* 50은 웹페이지 margin 값 */
if (scrollLocation + windowHeight >= fullHeight + 50) {
let loading = document.getElementById('load');
loading.style.display = "block";
setTimeout(more, 3000);
}
scrollFunction();
})
/* 로딩 종료 및 글 목록 추가 */
function more() {
let loading = document.getElementById('load');
loading.style.display = "none";
/* 무작위 갯수의 글 추가 */
for (let i = 0; i < Math.random() * 70; i++) {
lorem_ipsum(num++);
}
}
/* 버튼 보이는 이벤트 */
function scrollFunction() {
var btn = document.getElementById('btn');
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
btn.style.display = "block";
} else {
btn.style.display = "none";
}
}
/* 부드럽게 위로 가기 */
function GoTop() {
window.scrollTo({top:0, behavior:'smooth'});
}
view raw script.js hosted with ❤ by GitHub

Infinite Scrolling .html
0.00MB

'컴퓨터 > 프로젝트' 카테고리의 다른 글