Last active
August 12, 2020 10:54
-
-
Save ayaysir/3f36a4fe9066b8c8917382766501e106 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>IntersecionObserver: infinite scroll example</title> | |
<style> | |
body { | |
padding: 30px; | |
background-color: gray; | |
} | |
#container { | |
margin: 0px auto; | |
width: 500px; | |
} | |
#list { | |
padding: 0px; | |
} | |
#list li { | |
height: 250px; | |
line-height: 250px; | |
display: block; | |
background-color: aliceblue; | |
margin-bottom: 15px; | |
text-align: center; | |
vertical-align: middle; | |
font-size: 3em; | |
} | |
#msg-loading { | |
background-color: honeydew; | |
color: red; | |
text-align: center; | |
border-radius: 5px; | |
} | |
.fade-in { | |
opacity: 1; | |
animation-name: fadeInOpacity; | |
animation-iteration-count: 1; | |
animation-timing-function: ease-in; | |
animation-duration: 0.5s; | |
} | |
.fade-out { | |
opacity: 0; | |
animation-name: fadeOutOpacity; | |
animation-iteration-count: 1; | |
animation-timing-function: ease-in; | |
animation-duration: 0.5s; | |
} | |
@keyframes fadeInOpacity { | |
0% { | |
opacity: 0; | |
} | |
100% { | |
opacity: 1; | |
} | |
} | |
@keyframes fadeOutOpacity { | |
0% { | |
opacity: 0; | |
} | |
100% { | |
opacity: 1; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"> | |
<ul id="list"> | |
</ul> | |
<p id="msg-loading">....... 로딩중 .......</p> | |
</div> | |
<script> | |
let currentPage = 1 | |
const DATA_PER_PAGE = 10, | |
lastPage = 5 | |
const msgLoading = document.getElementById("msg-loading") | |
// 데이터 추가 함수 | |
function addData(currentPage) { | |
const $list = document.getElementById("list") | |
for (let i = (currentPage - 1) * DATA_PER_PAGE + 1; i <= currentPage * DATA_PER_PAGE; i++) { | |
const $li = document.createElement("li") | |
$li.textContent = `${currentPage}페이지 : ${i}번째 데이터` | |
$li.classList.add("fade-in") | |
$list.appendChild($li) | |
} | |
} | |
// IntersectionObserver 갱신 함수 | |
function observeLastChild(intersectionObserver) { | |
const listChildren = document.querySelectorAll("#list li") | |
listChildren.forEach(el => { | |
if (!el.nextSibling && currentPage < lastPage) { | |
intersectionObserver.observe(el) // el에 대하여 관측 시작 | |
} else if (currentPage >= lastPage) { | |
intersectionObserver.disconnect() | |
msgLoading.textContent = "페이지의 끝입니다." | |
} | |
}) | |
} | |
// IntersectionObeserver 부분 | |
const observerOption = { | |
root: null, | |
rootMargin: "0px 0px 0px 0px", | |
threshold: 0.5 | |
} | |
// IntersectionObserver 인스턴스 생성 | |
const io = new IntersectionObserver((entries, observer) => { | |
entries.forEach(entry => { | |
// entry.isIntersecting: 특정 요소가 뷰포트와 50%(threshold 0.5) 교차되었으면 | |
if (entry.isIntersecting) { | |
msgLoading.classList.add("fade-in") | |
// 다음 데이터 가져오기: 자연스러운 연출을 위해 setTimeout 사용 | |
setTimeout(() => { | |
addData(++currentPage) | |
observer.unobserve(entry.target) | |
observeLastChild(observer) | |
msgLoading.classList.remove("fade-in") | |
}, 1000) | |
} | |
}) | |
}, observerOption) | |
// 초기 데이터 생성 | |
addData(currentPage) | |
observeLastChild(io) | |
</script> | |
</body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment