图片懒加载(lazyLoad)实现方案总结

535 阅读2分钟

一.场景1

我们经常会用下载软件下载电视剧吧,一个电视剧可以能有N集。

    1.先把所所有的集数全部下载完成,然后一个个开开心心的看。你真的开心吗?
    2.我们先下一集,然后看完,看完以后再去下下一集,然后再看。
    3.我们先下第一集,下载完成以后,再看第一集的时候去下载后面的内容,这样,我们可以在看前面的内容的时候,把后面的下完了,节约了很多的时间
    

所以引出我们今天的问题 假如有一个幻灯片 这个幻灯片有1000张图片 你难道让网页初始化时去加载1000张吗?如果不做预加载,页面中会立刻生成1000个img标签,浏览器在接收到 HTML 文件并转换为 DOM 树会很消耗性能,并且会并发产生1000个http请求,势必会阻塞带宽。有一个办法就是,在页面刚打开的时候,我们去加载第一张图片,然后页面加载完成以后,在用户看的时间内,去加载后面的内容,

那么我们必须有个工具(迅雷) -> Image对象

Image用法

let oImage = new Image()

它有三个属性

src:当我们给Image对象的src属性赋值一个url的时候,这个Image对象就去会加载url资源,加载完成以后的资源被保存到了浏览器的缓存文件夹里面,下次如果我们要去调用这个url地址的时候,直接是从缓存文件夹读取到的,所以速度很快。

onload : 当资源加载完成的时候触发' onerror : 当资源加载失败的时候触发

图片的预先加载demo

<!DOCTYPE HTML>
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>图片预先加载</title>
	<script>
		window.onload = function () {

			var oImg = document.getElementById('img1');

			var oImage = new Image();

			var arr = [
				'http://d.hiphotos.baidu.com/image/w%3D2048/sign=2846dc1369600c33f079d9c82e74500f/a044ad345982b2b7938726c333adcbef76099b98.jpg',
				'http://f.hiphotos.baidu.com/image/w%3D2048/sign=2da141ad013b5bb5bed727fe02ebd439/7dd98d1001e9390124aacd3879ec54e736d1960f.jpg',
				'http://g.hiphotos.baidu.com/image/w%3D2048/sign=5e067f12a918972ba33a07cad2f57b89/b8014a90f603738d27674f24b11bb051f819ec83.jpg',
				'http://f.hiphotos.baidu.com/image/w%3D2048/sign=fc9023a7d343ad4ba62e41c0b63a5baf/4bed2e738bd4b31ca2a24ab985d6277f9e2ff812.jpg',
				'http://f.hiphotos.baidu.com/image/w%3D2048/sign=99191869cebf6c81f7372be88806b035/9345d688d43f8794a159b42fd01b0ef41bd53a08.jpg',
				'http://a.hiphotos.baidu.com/image/w%3D2048/sign=4aaddd39718da9774e2f812b8469f919/8b13632762d0f70391b28bd60afa513d2697c5b3.jpg',
				'http://g.hiphotos.baidu.com/image/w%3D2048/sign=50df8b2efffaaf5184e386bfb86c95ee/fc1f4134970a304ebbdb83f2d3c8a786c9175c38.jpg'
			];

			var iCur = 0;
			var i = 0;

			xunlei();

			oImg.onclick = function () {
				i++;
				if (i < arr.length) {
					oImg.src = arr[i];
				}
			}

			function xunlei() {
				oImage.src = arr[iCur];
				oImage.onload = function () {
					iCur++;
					if (iCur < arr.length) {
						xunlei();	//递归
					}
					document.title = iCur + ' / ' + arr.length;
				}
			}

		}
	</script>
</head>

<body>
	<img src="http://b.hiphotos.baidu.com/image/w%3D2048/sign=526ef7bda41ea8d38a227304a332314e/1ad5ad6eddc451dae05f4cedb4fd5266d016320e.jpg"
		id="img1" style="width: 300px;" />
</body>

</html>

二.场景2

比如上拉加载更多图片时,哪个标签出现到了可视区了,就代表用户是想看的,我们就只加载可视区的图片 怎么判断哪个img标签进入可视区了呢?

完整代码为

<!DOCTYPE HTML>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>图片按需加载</title>
    <style>
        #ul1 {
            margin: 100px auto 0;
            padding: 0;
        }

        li {
            float: left;
            margin: 0 0 10px 10px;
            list-style: none;
            border: 1px solid black;
        }

        img {
            width: 290px;
            height: 200px;
            display: block;
        }
    </style>
    <script>
        window.onload = function () {

            var oUl = document.getElementById('ul1');
            var aImg = oUl.getElementsByTagName('img');

            showImage();

            window.onscroll = showImage;

            function showImage() {

                var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                for (var i = 0; i < aImg.length; i++) {

                    if (!aImg[i].isLoad && getTop(aImg[i]) < scrollTop + document.documentElement.clientHeight) {
                        aImg[i].src = aImg[i].getAttribute('_src');
                        aImg[i].isLoad = true;
                    }

                }

            }
            function getTop(obj) {
                var iTop = 0;
                while (obj) {
                    iTop += obj.offsetTop;
                    obj = obj.offsetParent;
                }
                return iTop;
            }

        }
    </script>
</head>

<body>
    <ul id="ul1">
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/1.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/2.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/3.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/4.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/5.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/6.jpg" src="img/white.JPG" /></li>
        <li><img _src="img/7.jpg" src="img/white.JPG" /></li>
    </ul>
</body>

</html>

当然上面这种方式并不是最优解 因为每次滚动时都会进行for循环判断,试想以下,假如有1000张图片,就会循环1000次,这个计算量其实还是挺大的,还有一种方法就是创建一个数组,数组里面存储需要加载的图片,每加载玩一个,就从数组中删掉。也就是加载一张,数组就少一个,全部加载完成之后,数组为0,也就不会走循环了。