分享

手机网站实现图片惰性加载 | UC优视用户研究与体验设计中心

 沽渡 2014-09-09

什么是图片惰性加载呢?

顾名思义,惰性指的是我们只将用户视野范围内(浏览器窗口的可视区域)的图片加载,而用户视野范围外的图片先不加载,当用户看到这些图片时再做加载。

这样做的好处在于哪里呢?

1、用户访问速度上升了,浏览器的加载进度条很快就加载完毕。

2、节省用户流量。

那么如何实现呢?

我们需要解决两个问题:

① 如何知道用户是否能看见这张图片?

② 如何让看不到的图片不加载,而在需要的时候再去加载?

先解决第一个问题:如何知道用户是否能看见这张图片?

首先需要获取三个值,这些都可以通过javascript获取。

①浏览器窗口的高度 windowHeight

②页面滚动的距离    windowPageY

③图片距离页面顶部的距离 imgTop

 Javascript |  copy code |? 
1
if(imgTop >= windowPageY && imgTop <= (windowPageY+windowHeight)){
2
  //图片可见
3
}

关于上面的条件判断,相信你仔细思考就能看明白。

解决第二个问题:如何让看不到的图片不加载,而在需要的时候再去加载?

所有图片元素的src值先设置为一个很小的图片或者一张“加载中”的图片,而它的真实属性放置在一个自定义属性中如:


 HTML |  copy code |? 
1
<img dataimg="真实大图.png" src="小图.png">

这样浏览器只会去加载小图,而不会去加载大图,而当你所有图片都用同一张小图的时候,这张小图只需要加载一次,所以速度非常快。

当这张图片需要加载了,那么我们只需要将原先放置在自定义属性中的图片地址放置到img标签额src属性中就可以了,接下来浏览器就会去请求并加载这张图片:


 HTML |  copy code |? 
1
<img dataimg="真实大图.png" src="真实大图.png">

ok,基本原理就是这样,代码细节就不赘述了,直接贴代码。

lazyload.js


 Javascript |  copy code |? 
001
(function(){
002
/**
003
 * 功能:图片惰性加载。在需要图片惰性加载的页面底部载入。再将图片加上class=“lazy”。并将图片的真实地址放置在图片的自定义属性dataimg中。
004
 * @author haunghm
005
 * @version 1.0.0
006
 * @dependencies jquery 或者 zepto
007
 */
008
var lazyLoad = {
009
 
010
    init: function() {
011
        var that = this;
012
        that.onerrorImgUrl = "./images/grey.png";//图片加载失败用什么图片替换
013
        that.srcStore      = "dataimg";   //图片真实地址存放的自定义属性
014
        that.class         = "lazy";      //惰性加载的图片需要添加的class
015
        that.sensitivity   = 50;           //该值越小,惰性越强(加载越少)      
016
 
017
        minScroll = 5,
018
        slowScrollTime = 200,
019
        ios = navigator.appVersion.match(/(iPhone\sOS)\s([\d_]+)/),
020
        isIos = ios && !0 || !1,
021
        isoVersion = isIos && ios[2].split("_");
022
 
023
        isoVersion = isoVersion && parseFloat(isoVersion.length > 1 ? isoVersion.splice(0, 2).join(".") : isoVersion[0], 10),
024
        isIos = that.isPhone = isIos && isoVersion < 6;
025
 
026
        if (isIos) {
027
 
028
            var startSyAndTime,
029
            setTimeOut;
030
            $(window).on("touchstart",function() {
031
                startSyAndTime = {
032
                    sy: window.scrollY,
033
                    time: Date.now()
034
                },
035
                setTimeOut && clearTimeout(setTimeOut)
036
            }).on("touchend",function(e) {
037
                if (e && e.changedTouches) {
038
                    var subtractionY = Math.abs(window.scrollY &minus; startSyAndTime.sy);
039
                    if (subtractionY > minScroll) {
040
                        var subtractionTime = Date.now() &minus; startSyAndTime.time;
041
                        setTimeOut = setTimeout(function() {
042
                            that.changeimg(),
043
                            startSyAndTime = {},
044
                            clearTimeout(setTimeOut),
045
                            setTimeOut = null
046
                        },
047
                        subtractionTime > slowScrollTime ? 0: 200)
048
                    }
049
                } else {
050
                    that.changeimg();
051
                }
052
            }).on("touchcancel", function() {
053
                setTimeOut && clearTimeout(setTimeOut),
054
                startSyAndTime = {}
055
            })
056
        } else {
057
            $(window).on("scroll", function() {
058
                that.changeimg();
059
            });
060
        }
061
        setTimeout(function() {
062
            that.trigger();                
063
        },90);
064
 
065
    },
066
    trigger: function() {
067
        var that = this;
068
        eventType = that.isPhone && "touchend" || "scroll";
069
        that.imglist = $('img.'+that.class+'');
070
        $(window).trigger(eventType);
071
    },
072
    changeimg: function() {
073
        function loadYesOrno(img) {
074
            var windowPageYOffset = window.pageYOffset,
075
            windowPageYOffsetAddHeight = windowPageYOffset + window.innerHeight,
076
            imgOffsetTop = img.offset().top;
077
            return imgOffsetTop >= windowPageYOffset && imgOffsetTop &minus; that.sensitivity <= windowPageYOffsetAddHeight;
078
        }
079
        function loadImg(img, index) {
080
 
081
            var imgUrl = img.attr(that.srcStore);
082
            img.attr("src", imgUrl);
083
            img[0].onload || (img[0].onload = function() {
084
                $(this).removeClass(that.class).removeAttr(that.srcStore),
085
                that.imglist[index] = null,
086
                this.onerror = this.onload = null
087
            },
088
            img[0].onerror = function() {
089
                this.src = that.onerrorImgUrl,
090
                $(this).removeClass(that.class).removeAttr(that.srcStore),
091
                that.imglist[index] = null,
092
                this.onerror = this.onload = null
093
            })
094
        }
095
        var that = this;
096
        that.imglist.each(function(index, val) {
097
            if (!val) return;
098
            var img = $(val);
099
            if (!loadYesOrno(img)) return;
100
            if (!img.attr(that.srcStore)) return;
101
            loadImg(img, index);
102
        })
103
 
104
    }
105
};
106
lazyLoad.init();
107
 
108
}());

 

如何使用这个脚本呢?

 HTML |  copy code |? 
01
<!DOCTYPE html>
02
<html>
03
<head>
04
<title>图片惰性演示例子</title>
05
</head>
06
<body>
07
<img class="lazy" dataimg="images/change01.jpg" src="./grey.png">
08
<img class="lazy" dataimg="images/change02.jpg" src="./grey.png">
09
<img class="lazy" dataimg="images/change03.jpg" src="./grey.png">
10
<img class="lazy" dataimg="images/change04.jpg" src="./grey.png">
11
<img class="lazy" dataimg="images/change05.jpg" src="./grey.png">
12
<img class="lazy" dataimg="images/change06.jpg" src="./grey.png">
13
</body>
14
 
15
<script src="http://libs.baidu.com/zepto/1.0rc/zepto.min.js"></script>
16
<script src="./lazyload.js"></script>
17
 
18
</html>

 
就像上面的代码一样,很简单。只要在页面底部载入jquery或者zepto(如果你不想依赖这两个库,也很简单,可以改造一下代码,毕竟在移动端不需要处理很多兼容性问题)。然后载入lazyload.js这个脚本。

并按照一下规则来书写你的img标签

 HTML |  copy code |? 
1
<img class="lazy" dataimg="真实大图.png" src="小图.png">

注意事项:图片最好都用样式定义高度,否则图片的高度默认为0,就上面的例子来讲,所有img标签都挤在一起,全部在第一屏,导致程序认为它们都应该加载,就看不到效果了。

好了,高潮和结局终于同时来了。我始终认为demo也需要有赏心悦目的感觉。

二维码访问:

demo下载: lazyload

本文参考了m.taobao.com的代码。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多