前言
按需要加载图片,这是一个非常实用的功能,不仅可以提高网站的性能,还可以为你节省流量。对于用虚拟主机的朋友来说,如果你的网站是一个图片网站或者图片比较多的网站,那么图片懒加载功能真不能少。
原理
实现图片懒加载的原理也非常地简单,默认情况下不给图片 scr 属性赋值。当满足一定的条件时才把图片地址取出来赋值给 src 属性。一般地,这上为了让网站页面有更好的用户体验,我们都会预先给所有的图片都设置一张默认的图片,比如一个像素的图片或者其它任意一张图片(只要你喜欢)。
实践代码
我们还是先来看看这个 Demo:http://yunkus.com/demo/load-images-on-demand/
例子中用了一个谈入的效果(CSS 3),如果你想用更多的效果,你可以下载一下 animate.css 库,尝试不同效果展示。在这里就不作过多的讲解,至于 animate.css 库的用法你可以参考这里:
Animate.css 使用教程(一个强大的 CSS3 动画库)。
CSS 样式
.lazy-img-box {
margin: 0 auto;
width: 430px;
overflow: hidden
}
.lazy-img-box li {
list-style: none;
float: left;
width: 400px;
height: 200px;
margin-right: 12px;
margin-bottom: 12px;
}
.lazy-img-box li img {
width: 400px;
height: 200px;
display: block;
}
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>按需加载图片(图片懒加载)-云库网</title>
<meta name="description" content="按需加载图片不仅提高网站性能,还可以为你省了不少流量!" />
<meta name="keywords" content="JavaScript教程,按需加载图片,图片懒加载" />
<link rel="stylesheet" href="./index.css">
</head>
<body>
<ul class="lazy-img-box">
<li><img _src="http://yunkus.com/demo/lib/images/demo-1.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-2.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-3.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-4.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-5.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-6.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-7.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-8.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-9.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-1.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-2.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-3.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-4.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-5.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-6.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-7.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-8.jpg" src="./images/loading.gif" alt=""></li>
<li><img _src="http://yunkus.com/demo/lib/images/demo-9.jpg" src="./images/loading.gif" alt=""></li>
</ul>
<script src="./index.js"></script>
</body>
</html>
JavaScript 代码
window.onload = function () {
var lazyImg = document.getElementsByTagName("img");
var lazyImgLen = lazyImg.length;
var lazyImgArray = [];
var winowBroswerHeight = document.documentElement.clientHeight;
// 初始第一屏图片
loadImg();
// 滚动时执行加载图片的方法
window.onscroll = loadImg;
// 按需加载图片
function loadImg() {
for (var i = 0; i < lazyImgLen; i++) {
var getTD = getTopDistance(lazyImg[i]);
var getST = getScrollTop();
if (!lazyImg[i].loaded && getST < getTD && getTD < (getST + winowBroswerHeight)) {
lazyImg[i].src = lazyImg[i].getAttribute("_src");
lazyImg[i].classList.add("animated", "fadeIn");
lazyImg[i].loaded = true; // 标记为已加载
}
}
}
// 获取目录对象离 document 文档顶部的距离
function getTopDistance(obj) {
var TopDistance = 0;
while (obj) {
TopDistance += obj.offsetTop;
obj = obj.offsetParent;
}
return TopDistance;
}
// 获取滚动条的滚动距离
function getScrollTop() {
return document.documentElement.scrollTop || document.body.scrollTop;
}
}
不管滚动条处于什么位置,只要你一刷新,就只会加载处于屏幕里的图片。除此之处不管是屏幕上方的图片,还是屏幕下方的图片只要还没进入屏幕区的都不会被加载。这样的处理方式理论上是比较优的,但是在实践的应用中,却不一定能发展出原有的作用。试想一下,不管你是通过地址直接访问,还是通过搜索引擎进入一个页面,一般情况下都会从页面的顶部内容开始显示,如果你有洁癖想让代码更简单,那么 loadImg() 方法就可以更改成如下代码:
function loadImg() {
for (var i = 0; i < lazyImgLen; i++) {
var getTD = getTopDistance(lazyImg[i]);
var getST = getScrollTop();
if (!lazyImg[i].loaded && getTD < (getST + winowBroswerHeight)) {
lazyImg[i].src = lazyImg[i].getAttribute("_src");
lazyImg[i].classList.add("animated", "fadeIn");
lazyImg[i].loaded = true; // 标记为已加载
}
}
}
其实也没什么变的,只是 if 判断条件少了一个:
getST < getTD
不过也有例外,比如:从列表页中点了评论时,极有可能是跳到详情页后直接跳到评论区,这种情况也很常见,此时就不需要更改代码以达到最优。
这里还有个小问题,关于滚动监听事件的,像上面那样写 window.onscroll = function(){} 一个页面只能用一个,如果有其它地主也用到这个滚动监听事件的话,那么就会只有一个起作用。在这里可以用事件绑定来解决,具体的方法可以查阅这里:常用的 JavaScript 函数封装。