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>.
        &copy; 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

 

Intersection Observer API - Web APIs | MDN

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.

developer.mozilla.org

 

https://www.section.io/engineering-education/intersection-observer-api/

 

 

아직도 이 API 모르셨다고요? 개발자 인생 꿀템 소개!

https://www.youtube.com/watch?v=iZhq7I42uaI 


댓글

가장 많이 본 글

인천국제공항 제1여객터미널에서 일본으로 가는 출국 절차 안내 ✈️

빅데이터 시대의 도구, LUCY 2.0

Playwright MCP 설정 및 활용 방법