javascript : 스크롤 시 이미지 지연 로딩, 무한 스크롤 구현, Intersection Observer 를 활용하자.
Intersection Observer 를 활용하자.
Intersection Observer 는 요소(대상)와 다른 요소(루트) 또는 뷰포트의 교차점에서 변경 사항을 효율적으로 관찰할 수 있는 내장 JavaScript API입니다. 스크롤 또는 기타 DOM 변경 중에 요소가 사용자 보기 내에서 표시되거나 숨겨지는 시기를 감지하는 데 특히 유용합니다.
이는 스크롤하는 동안 특정 클래스가 화면에 표시될 때 AJAX를 통해 더 많은 항목을 로드하도록 코드를 구현하고자 합니다. 이를 달성하기 위해 요소가 viewport 에 들어가거나 나갈 때 요소를 관찰할 수 있는 Intersection Observer API 를 사용할 수 있습니다.
Intersection Observer를 사용하는 업데이트된 코드는 다음과 같습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infinite Scroll Example</title>
<!-- Include jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div id="list-container">
<!-- Your initial list contents go here -->
<ul id="list">
<!-- Add more initial list items here -->
</ul>
<div class="load-more-placeholder"></div>
</div>
<script>
// JavaScript code goes here
$(document).ready(function() {
let isLoading = false; // Flag to prevent multiple AJAX calls simultaneously
setTimeout(function() {
// Generate some additional list items
let items = '';
for (let i = 1; i <= 10; i++) {
items += '<li>Item ' + ($('#list li').length + i) + '</li>';
}
// Append the new list items to the list container
$('#list').append(items);
}, 1); // Simulate AJAX delay
// Function to simulate the AJAX call and add more list items
function loadMoreItems() {
// Simulate an AJAX call with a delay
setTimeout(function() {
// Generate some additional list items
let items = '';
for (let i = 1; i <= 10; i++) {
items += '<li>Item ' + ($('#list li').length + i) + '</li>';
}
// Append the new list items to the list container
$('#list').append(items);
isLoading = false; // Reset the isLoading flag
}, 500); // Simulate AJAX delay
}
// Function to handle the intersection observer event
function handleIntersection(entries, observer) {
entries.forEach(entry => {
if (entry.intersectionRatio > 0 && !isLoading) {
// Call the AJAX function when the load-more-placeholder becomes visible
isLoading = true; // Set the isLoading flag to prevent multiple calls
loadMoreItems();
}
});
}
// Create the Intersection Observer and start observing the load-more-placeholder
const observer = new IntersectionObserver(handleIntersection, {
root: null,
rootMargin: '0px',
threshold: 0.1, // When 10% or more of the load-more-placeholder is visible
});
// Start observing the load-more-placeholder
const loadMorePlaceholder = document.querySelector('.load-more-placeholder');
observer.observe(loadMorePlaceholder);
});
</script>
</body>
</html>
이 업데이트된 코드에서 #list-container 끝에 load-more-placeholder div를 추가했습니다. Intersection Observer는 이 요소를 감시하도록 설정되어 있으며 화면에 10% 이상이 표시되면 'handleIntersection' 기능이 트리거됩니다. 이 함수는 동시에 여러 호출을 방지하기 위해 AJAX 호출이 이미 진행 중인지(isLoading 플래그) 확인합니다. 진행 중인 AJAX 호출이 없으면 'loadMoreItems' 함수를 호출하여 추가 목록 항목을 로드합니다.
이제 스크롤하는 동안 load-more-placeholder가 표시되면 AJAX를 통해 새 항목이 로드됩니다. 이 접근 방식은 불필요한 AJAX 호출 없이 새 콘텐츠 로드를 효율적으로 처리해야 합니다.
Intersection Observers 활용한 이미지 lazy loading 구현하기
* index.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family:monospace,sans-serif;
}
body::-webkit-scrollbar{
width: 10px;
}
body::-webkit-scrollbar-track{
background-color: black;
}
body::-webkit-scrollbar-thumb{
background-color: white;
}
nav{
display: flex;
justify-content: space-between;
align-items: center;
background-color: coral;
padding: 1.5rem 0;
}
nav h1{
font-size: 2rem;
color:white;
}
h2{
color:rgb(255, 32, 225);
text-align: center;
font-size: 2.5rem;
}
a{
text-decoration: none;
font-size: 1.5rem;
color: white;
}
.image-container{
background-color: #d5d6d5;
}
img{
width: 60vw;
height: 450px;
transform: translateX(50%);
opacity: 0;
transition: all 900ms;
}
.fade{
transform: translateX(0);
opacity: 1.0;
transition: all 900ms;
}
footer{
background-color: rgb(8, 7, 10);
padding: 1.8rem;
color: #ffffff;
}
코드 설명
- const targets=document.querySelectorAll("img")은 DOM의 모든 이미지를 가져옵니다.
- lazyLoad 함수는 DOM 엘리먼트를 인수로 받습니다. 이 함수 내에서 두 개의 매개변수가 있는 콜백을 받는 io라는 이름의 옵저버 객체를 만듭니다.
- 첫 번째 매개변수 항목은 요소에 대한 실제 관찰이고, 관찰자 매개변수는 이 관찰자의 인스턴스를 관리하는 데 사용되는 인터페이스입니다.
- entries.forEach 메서드는 항목에 대해 반복합니다. 루프 내부에서는 entry.isIntersecting으로 이미지가 뷰포트와 교차하는지 확인합니다.
- 이미지가 교차하면 img.setAttribute("src",src)를 호출하여 데이터-src 속성에서 src 속성을 추가한 다음 img.classList.add() 메서드를 사용하여 페이드 클래스를 추가합니다.
- 각 이미지에는 고유한 옵저버가 있으므로 observer.disconnect() 메서드를 호출하여 이미지 옵저버를 폐기할 수 있습니다. 옵션 객체는 0.7의 임계값을 사용합니다.
- io.observe(target)는 이미지 가시성을 관찰하는 메서드입니다.
이제 이미지가 포함된 타깃을 반복하고 lazyLoad 콜백 함수를 전달하여 IntersectionObserver가 관찰할 수 있도록 해야 합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<nav>
<h1>MY GALLERY</h1>
<div>
<a href="#">About</a>
<a href="#">Register</a>
<a href="#">Login</a>
</div>
</nav>
<h2>This is my Gallery Website</h2>
<div class="images-container">
<img data-src="./images/ai.jpg" alt="">
<img data-src="./images/code.jpg" alt="">
<img data-src="./images/fg.jpg" alt="">
<img data-src="./images/hero.jpg" alt="">
<img data-src="./images/images.jpg" alt="">
<img data-src="./images/lapt.jpg" alt="">
<img data-src="./images/lock.jpg" alt="">
<img data-src="./images/lpt.jpg" alt="">
</div>
<footer>
Built by Wilson Njugia <a href="https://github.com/reactifyStudio">-reactifyStudio</a>.
© 2020. All rights reserved.
</footer>
<script>
const targets=document.querySelectorAll("img");
const lazyLoad=target=>{
const io = new IntersectionObserver((entries,observer)=>{
entries.forEach(entry=>{
if(entry.isIntersecting){
const img=entry.target;
const src=img.getAttribute("data-src");
img.setAttribute("src",src);
img.classList.add("fade");
observer.disconnect();
}
})
},{threshold:[0.7]});
io.observe(target);
}
targets.forEach(lazyLoad);
</script>
</body>
</html>
참고 사이트
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
https://www.section.io/engineering-education/intersection-observer-api/
아직도 이 API 모르셨다고요? 개발자 인생 꿀템 소개!
https://www.youtube.com/watch?v=iZhq7I42uaI
댓글
댓글 쓰기