자바스크립트 예제: 스크롤 이벤트를 사용한 이미지 지연 로딩(lazy loading) 라이브러리 없이
참고
- 자바스크립트: IntersectionObserver (1) 이미지 lazy-loading 구현
- jQuery: 제이쿼리 이미지 지연 로딩(lazy loading) 플러그인 (jQuery Lazy)
- 자바스크립트: 무한 스크롤 (스크롤 이벤트 이용, 라이브러리 없이)
intersectionObserver를 사용하지 않고 마우스 스크롤 이벤트를 이용해 이미지 지연 로딩(lazy loading)을 하는 방법입니다.
이미지 지연 로딩이란 웹 페이지를 렌더링할때 이미지를 불러오지 않고 사용자가 특정 영역을 클릭하거나 스크롤을 하여 이미지 영역이 눈에 보이는 뷰포트(viewport) 안에 들어왔을 때 이미지를 로딩하여 낮은 인터넷속도에서도 쾌적한 로딩을 하기 위한 기법을 말합니다.
여기서는 마우스의 스크롤 이벤트를 사용하며, 이미지 영역이 뷰포트에 들어왔을 때 이미지를 로딩합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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 관련)
This post is licensed under
CC BY 4.0
by the author.
