참고

 

intersectionObserver를 사용하지 않고 마우스 스크롤 이벤트를 이용해 이미지 지연 로딩(lazy loading)을 하는 방법입니다.

이미지 지연 로딩이란 웹 페이지를 렌더링할때 이미지를 불러오지 않고 사용자가 특정 영역을 클릭하거나 스크롤을 하여 이미지 영역이 눈에 보이는 뷰포트(viewport) 안에 들어왔을 때 이미지를 로딩하여 낮은 인터넷속도에서도 쾌적한 로딩을 하기 위한 기법을 말합니다.

여기서는 마우스의 스크롤 이벤트를 사용하며, 이미지 영역이 뷰포트에 들어왔을 때 이미지를 로딩합니다.

 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Load lazy image by scroll-height</title>
    <style>
        .img-box {
            height: 500px;
            border: 1px solid black;
        }

        .img-box img {
            height: 500px;
        }
    </style>
</head>

<body>
    <!--    초기 화면에 들어오는 이미지는 not lazy, 화면 밖에 있는 이미지는 lazy-->
    <div class="img-box">
        <img src="https://i.ibb.co/N7tQQNC/1-Chrysanthemum.jpg">
    </div>
    <div class="img-box">
        <img src="https://i.ibb.co/MB0whn7/2-Desert.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/jJ9nV4n/3-Hydrangeas.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/QcKyxtR/4-Jellyfish.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/D78YHNc/5-Koala.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/HP0QKQR/6-Lighthouse.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/6J3L9Kb/7-Penguins.jpg">
    </div>
    <div class="img-box lazy">
        <img data-src="https://i.ibb.co/Rj41Xwr/8-Tulips.jpg">
    </div>

    <script>
        // .. 스크립트 삽입 .. //
    </script>
</body></html>
function debounce(callback, limit = 100) {
    let timeout
    return function(...args) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            callback.apply(this, args)
        }, limit)
    }
}

const imgBoxes = document.querySelectorAll(".img-box.lazy")

const loadLazyImg = debounce(e => {

    // clientHeight : 웹 브라우저 창의 높이
    // scrollTop : 현재 스크롤된 부분의 맨 위의 높이
    // scrollHeight : 문서의 총 높이 (= 스크롤의 총 높이)
    // (이미지 lazy) 해당 이미지가 현재 스크롤 화면에 들어옴 : clientHeight + scrollTop >= box.offsetTop
    // (참고: 무한스크롤) 스크롤의 마지막에 도달 : clientHeight + scrollTop >= scrollHeight
    // window.innerHeight = clientHeight

    const {
        clientHeight,
        scrollTop,
        scrollHeight
    } = e.target.scrollingElement


    imgBoxes.forEach(box => {
        if (box.offsetTop < clientHeight + scrollTop) {
            const $img = box.querySelector("img")
            $img.src = $img.dataset.src
            $img.classList.remove("lazy")
        }
    })

}, 200)


// ===== 이미지 로딩 =====
document.addEventListener("scroll", loadLazyImg)

// 출처: https://velog.io/@boh001/Infinity-Scrolling
  • 마우스 스크롤 이벤트를 사용하기 때문에 최적화를 위해 콜백 실행시 debounce 또는 throttle 함수를 사용합니다.
  • clientHeight + scrollTop 는 현재까지 스크롤된 영역까지의 높이를 말하며 box.offsetTop은 이미지 영역의 top 위치를 말합니다. 현재까지 스크롤된 영역 안에 box.offsetTop이 있다면 이미지가 뷰포트에 나타난 상태이므로 이미지 지연 로딩을 시작하고, 아직 스크롤된 영역 밖에 있다면 뷰포트에 나타나지 않은 상태이므로 대기합니다.
  • data-src 속성에 이미지 주소를 저장하고, 지연 로딩 시작시 data-src의 주소를 src 속성에 지정합니다.
  • 처음부터 나타나는 이미지 몇 개는 지연 로딩을 하지 않는것이 좋습니다. (SEO 관련)

 

 

출처: https://velog.io/@boh001/Infinity-Scrolling


문의 | 코멘트 또는 yoonbumtae@gmail.com  donaricano-btn

카테고리: WEB: Frontend

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다