图片 - 懒加载
图片的懒加载其实就是延迟加载图片,仅当图片出现在可视区域内(或离可视区域有一定距离时)才开始加载图片。
对于有大量图片的网页来说,懒加载可以避免在打开网页时同时加载过多资源,起到性能优化的作用。
原理
初始加载时不设置img
的src
属性(或者src
属性设置成占位图片地址),将真实的图片地址放置在 data-src
属性里,后续当图片进入到页面的可视区域后,将data-src
属性值取出赋值给src
属性,此时再去请求图片
相关插件
如何判断图片处于页面可视区域?
方法一:getBoundingClientRect (推荐)
Element.getBoundingClientRect()
方法返回一个DOMRect
对象,该对象包含的属性包括Element
元素的大小(width
、height
)及其相对于视口左上角的位置(top
、left
、right
、bottom
)
function isInViewport(el) {
const rect = el.getBoundingClientRect()
const viewportSize = getViewportSize()
const vpHeight = viewportSize.width
const vpWidth = viewportSize.height
return 0 < rect.bottom && rect.top < vpHeight ||
0 < rect.right && rect.left < vpWidth
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
方法二:offsetTop/offsetLeft、scrollTop/srollLeft
function isInViewport(el) {
const scrollOffset = getScrollOffset()
const scrollTop = scrollOffset.scrollTop
const scrollLeft = scrollOffset.scrollLeft
const viewportSize = getViewportSize()
const vpHeight = viewportSize.height
const vpWidth = viewportSize.width
const height = el.offsetHeight
const width = el.offsetWidth
const elPos = getElementPosition(el)
const offsetLeft = elPos.offsetLeft
const offsetTop = elPos.offsetTop
return -height < offsetTop - scrollTop && offsetTop - scrollTop < vpHeight ||
-width < offsetLeft - scrollLeft && offsetLeft - scrollLeft < vpWidth
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
方法三:原生 IntersectionObserver 函数
Referrence:
- justjavac:IntersectionObserver #10open in new window
- 阮一峰:IntersectionObserver API 使用教程open in new window
- 原生JS实现最简单的图片懒加载open in new window
工具函数
// 获取视口尺寸
function getViewportSize(win = window) {
if (win.innerWidth !== undefined) {
return {
width: window.innerWidth,
height: window.innerHeight
}
}
const doc = win.document
if (doc.compatMode === 'CSS1Compat') {
// 标准模式下的 IE(或任何浏览器)
return {
width: doc.documentElement.clientWidth,
height: doc.documentElement.clientHeight
}
}
// 怪异模式下的浏览器
return {
width: doc.body.clientWidth,
height: doc.body.clientHeight
}
}
// 获取元素距离文档的距离
function getElementPosition(el) {
let offsetLeft = 0, offsetTop = 0
while(el !== undefined) {
offsetLeft += el.offsetLeft
offsetTop += el.offsetTop
el = el.offsetParent
}
return {
offsetLeft
offsetTop
}
}
// 获取文档的滚动距离
function getScrollOffset(win = window) {
if (win.pageXOffset !== undefined) {
// 除了 IE8 及更早版本,其他浏览器都能用
return {
scrollTop: win.pageYOffset,
scrollLeft: win.pageXOffset
}
}
const doc = win.document
if (doc.compatMode === 'CSS1Compat') {
// 标准模式下的 IE(或任何浏览器)
return {
scrollTop: doc.documentElement.scrollTop,
scrollLeft: doc.documentElement.scrollLeft
}
}
// 怪异模式下的浏览器
return {
scrollTop: doc.body.scrollTop,
scrollLeft: doc.body.scrollLeft
}
}
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62