JS怎样实现图片的懒加载以及jquery.lazyload.js的使用

在项目中有时候会用到图片的延迟加载,那么延迟加载的好处是啥呢?

我觉得主要包括两点吧,第一是在包含很多大图片长页面中延迟加载图片可以加快页面加载速度;第二是帮助降低服务器负担。

下面介绍一下常用的延迟加载插件jquery.lazyload.js以及怎样实现一个延迟加载的插件。

一:jquery.lazyload.js插件

lazyload是jQuery写的延迟加载插件,在浏览器可视区域外的图片不会被载入,直到用户将页面滚动到它们所在的位置. 这与图片预加载的处理方式正好是相反的。

实现原理

首先选中的img元素都绑定了一个appear事件(处理img显示真实的图片地址),方便以后满足条件时触发该事件;

在配置对象中有一个container属性配置,默认为window,如果img元素在该container容器视口中,则触发appear事件;

为了判断img元素是否在container容器视口范围中,有如下四个方法:

$.belowthefold = function(element,settings) {};    // 在视口下方
$.rightoffold =  在视口右方
$.abovethetop =  在视口上方
$.leftofbegin =  在视口左方

具体使用

1.页面引入方式

由于延迟加载lazyload是依赖jquery的,所有页面需要引入jquery,如下:

<script src="jquery.js"></script>
="jquery.lazyload.js">

基本写法:

<img class="lazy" data-original="img/example.jpg" width="640" height="480">

$(function() {
    $("img.lazy").lazyload();
});

其中的data-original 属性存放真实的图片url路径。

小贴士:你必须设置图片的宽度或者高度在css中,否则插件可能不能正常工作。

设置Threshold

默认情况下图片会出现在屏幕时加载. 如果你想提前加载图片,可以设置 threshold 选项,设置 threshold 为 200 令图片在距离屏幕 200 像素时提前加载。

$("img.lazy").lazyload({
    threshold : 200
});

设置事件触发加载

事件可以是任何 jQuery 事件,如: click 和 mouseover. 你还可以使用自定义的事件,如: sporty 和 foobar. 默认情况下处于等待状态,直到用户滚动到窗口上图片所在位置. 在灰色占位图片被点击之前阻止加载图片,你可以这样做:

$("img.lazy").lazyload({
    event : "click"
});

当然,你也可以用下面的这种方式实现延迟加载:

$().lazyload({
        event : "sporty"
    });
});

$(window).bind("load",() {
    var timeout = setTimeout(() {
        $("img.lazy").trigger("sporty")
    },5000);
});

即是页面加载完成 5 秒后,再去执行图片的懒加载。

延迟加载效果

当图片完全加载的时候,插件默认地使用 show() 方法来将图显示出来. 其实你可以使用任何你想用的特效来处理. 下面的代码使用 FadeIn 效果:

$("img.lazy").lazyload({
    effect : "fadeIn"
});

不支持JavaScript的浏览器的使用方式

几乎所有浏览器的 JavaScript 都是激活的. 然而可能你仍希望能在不支持 JavaScript 的客户端展示真实图片. 当浏览器不支持 JavaScript 时优雅降级,你可以将真实的图片片段在写 <noscript> 标签内。

img class="lazy" data-original="img/example.jpg"  width="640" heigh="480"noscript>
     width</>

可以通过 CSS 隐藏占位符:

.lazy {
  display: none;
}

在支持 JavaScript 的浏览器中,你必须在 DOM ready 时将占位符显示出来,这可以在插件初始化的同时完成。

$("img.lazy").show().lazyload();

设置延迟加载的图片容器

你可以将插件用在可滚动容器的图片上,例如带滚动条的 DIV 元素. 你要做的只是将容器定义为 jQuery 对象并作为参数传到初始化方法里面:

#container {
    height: 600px;
    overflow: scroll;
}

$("img.lazy").lazyload({
    container: $("#container")
});

当图片不顺序排列

滚动页面的时候,Lazy Load 会循环为加载的图片. 在循环中检测图片是否在可视区域内. 默认情况下在找到第一张不在可见区域的图片时停止循环. 图片被认为是流式分布的,图片在页面中的次序和 HTML 代码中次序相同. 但是在一些布局中,这样的假设是不成立的. 不过你可以通过 failurelimit 选项来控制加载行为。

$("img.lazy").lazyload({ 
    failure_limit : 10
});

将 failurelimit 设为 10 令插件找到 10 个不在可见区域的图片是才停止搜索. 如果你有一个猥琐的布局,请把这个参数设高一点。

设置加载隐藏的图片

可能在你的页面上埋藏可很多隐藏的图片. 比如插件用在对列表的筛选,你可以不断地修改列表中各条目的显示状态. 为了提升性能,Lazy Load 默认忽略了隐藏图片. 如果你想要加载隐藏图片,请将 skip_invisible 设为 false。

$("img.lazy").lazyload({
    skip_invisible : true
});

源码

官网地址:http://appelsiini.net/projects/lazyload/

/*!
     * Lazy Load - jQuery plugin for lazy loading images
     *
     * Copyright (c) 2007-2015 Mika Tuupola
     *
     * Licensed under the MIT license:
     *   http://www.opensource.org/licenses/mit-license.php
     *
     * Project home:
     *   http://www.appelsiini.net/projects/lazyload
     *
     * Version:  1.9.7
     *
     */
    
    (($,window,document,undefined) {
        var $window = $(window);
    
        $.fn.lazyload = (options) {
            var elements = this;
            var $container;
            var settings = {
                threshold       : 0,failure_limit   : 0falsenull"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"
            };
    
             update() {
                var counter = 0;
    
                elements.each(() {
                    var $this = $();
                    if (settings.skip_invisible && !$this.is(":visible")) {
                        return;
                    }
                    if ($.abovethetop(this,settings) ||
                        $.leftofbegin( Nothing. 
                    } else if (!$.belowthefold(this.trigger("appear");
                             if we found an image we'll load,reset the counter 
                            counter = 0;
                    } else {
                        if (++counter > settings.failure_limit) {
                            return ;
                        }
                    }
                });
    
            }
    
            if(options) {
                 Maintain BC for a couple of versions. */
                if (undefined !== options.failurelimit) {
                    options.failure_limit = options.failurelimit;
                    delete options.failurelimit;
                }
                 options.effectspeed) {
                    options.effect_speed = options.effectspeed;
                     options.effectspeed;
                }
    
                $.extend(settings,options);
            }
    
             Cache container as jQuery as object. 
            $container = (settings.container === undefined ||
                          settings.container === window) ? $window : $(settings.container);
    
             Fire one scroll event per scroll. Not one scroll event per image. */
            if (0 === settings.event.indexOf("scroll")) {
                $container.bind(settings.event, update();
                });
            }
    
            this.each(() {
                var self = ;
                var $self = $(self);
    
                self.loaded = ;
    
                 If no src attribute given use data:uri. if ($self.attr("src") === undefined || $self.attr("src") === ) {
                    if ($self.is("img")) {
                        $self.attr("src" When appear is triggered load original image. 
                $self.one("appear",1)">if (!.loaded) {
                         (settings.appear) {
                            var elements_left = elements.length;
                            settings.appear.call(self,elements_left,settings);
                        }
                        $("<img />")
                            .bind("load",1)">() {
    
                                var original = $self.attr("data-" + settings.data_attribute);
                                $self.hide();
                                )) {
                                    $self.attr("src" {
                                    $self.css("background-image","url('" + original + "')");
                                }
                                $self[settings.effect](settings.effect_speed);
    
                                self.loaded = ;
    
                                 Remove image from array so it is not looped next time. */
                                var temp = $.grep(elements,1)">(element) {
                                    return !element.loaded;
                                });
                                elements = $(temp);
    
                                 (settings.load) {
                                     elements.length;
                                    settings.load.call(self,settings);
                                }
                            })
                            .attr("src",$self.attr("data-" + settings.data_attribute));
                    }
                });
    
                 When wanted event is triggered load original image  by triggering appear.                              if (0 !== settings.event.indexOf("scroll")) {
                    $self.bind(settings.event,1)">() {
                        self.loaded) {
                            $self.trigger("appear");
                        }
                    });
                }
            });
    
             Check if something appears when window is resized. 
            $window.bind("resize",1)">() {
                update();
            });
    
             With IOS5 force loading images when navigating with back button.  Non optimal workaround. if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {
                $window.bind("pageshow",1)">(event) {
                    if (event.originalEvent && event.originalEvent.persisted) {
                        elements.each(() {
                            $(this).trigger("appear");
                        });
                    }
                });
            }
    
             Force initial check if images should appear. 
            $(document).ready(;
        };
    
         Convenience methods in jQuery namespace.           */
         Use as  $.belowthefold(element,{threshold : 100,container : window}) 
    
        $.belowthefold = (element,settings) {
             fold;
    
            if (settings.container === undefined || settings.container === window) {
                fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();
            }  {
                fold = $(settings.container).offset().top + $(settings.container).height();
            }
    
            return fold <= $(element).offset().top - settings.threshold;
        };
    
        $.rightoffold =  window) {
                fold = $window.width() + $window.scrollLeft();
            }  {
                fold = $(settings.container).offset().left + $(settings.container).width();
            }
    
            return fold <= $(element).offset().left - settings.threshold;
        };
    
        $.abovethetop =  window) {
                fold = {
                fold = $(settings.container).offset().top;
            }
    
            return fold >= $(element).offset().top + settings.threshold  + $(element).height();
        };
    
        $.leftofbegin =  $(settings.container).offset().left;
            }
    
            return fold >= $(element).offset().left + settings.threshold + $(element).width();
        };
    
        $.inviewport = return !$.rightoffold(element,settings) && !$.leftofbegin(element,settings) &&
                    !$.belowthefold(element,settings) && !$.abovethetop(element,settings);
         };
    
         Custom selectors for your convenience.    Use as $("img:below-the-fold").something() or  $("img").filter(":below-the-fold").something() which is faster 
    
        $.extend($.expr[":"],{
            "below-the-fold" : function(a) { return $.belowthefold(a,{threshold : 0}); },"above-the-top"  : return !$.belowthefold(a,"right-of-screen": return $.rightoffold(a,"left-of-screen" : return !$.rightoffold(a,"in-viewport"    : return $.inviewport(a,1)"> Maintain BC for couple of versions. */
            "above-the-fold" : }); }
        });
    
    })(jQuery,document);

二:手写一个简单的懒加载插件

js代码

window.smallDelay = ((window,undefined) {
    'use strict';
    var store = [],poll;
     {
        offset:0,1)">离可视区域多少像素的图片可以被加载
        throttle: 250 图片延时多少毫秒加载
    }
        
    var _inView = (el) {
        var coords = el.getBoundingClientRect();
        return ((coords.top >= 0 && coords.left >= 0) && coords.top <= ((window.innerHeight || document.documentElement.clientHeight) + parseInt(settings.offset)));
    };

    var _pollImages = () {
        for (var i = store.length; i--;) {
            var self = store[i];
             (_inView(self)) {
                self.src = self.getAttribute('data-delay');
                store.splice(i,1);
            }
        }
    };

    var _throttle = () {
        clearTimeout(poll);
        poll = setTimeout(_pollImages,settings.throttle);
    };

    var init = (obj) {
        var nodes = document.querySelectorAll('[data-delay]');
        var opts = obj || {};
        settings.offset = opts.offset || settings.offset;
        settings.throttle = opts.throttle || settings.throttle;

        var i = 0; i < nodes.length; i++) {
            store.push(nodes[i]);
        }

        _throttle();
        
        滚动监听执行图片懒加载
         (document.addEventListener) {
            window.addEventListener('scroll',_throttle,1)">);
        }  {
            window.attachEvent('onscroll'返回该对象进行链式操作
        ;
    };

     {
        init: init,render: _throttle
    };

})(window,document);

调用方式:

smallDelay.init({
     offset: 0,1)">离可视区域多少像素的图片可以被加载
   throttle: 0 图片延时多少毫秒加载
});

html代码:

="images/loading.gif" data-delay="images/avatar.png" />

三:根据lazyload插件实现一个不依赖jQuery的懒加载插件

实现内容

1、增加了图片预加载可选

2、修改了图片本身就在可视范围的时候直接显示而不需要滚动条触发

3、修改了Splice删除数组的时候,会跳过下一张图片BUG

4、浏览器窗口resize的时候图片出现也会加载

5、判断图片父层包裹顶部或者底部出现在可视范围内即可显示图片

实现源码

var Lazy = {
        $:(arg,context){
            var tagAll,n,eles=[],i,sub = arg.substring(1);
            context = context|| document;
            if(typeof arg =='string'){
                switch(arg.charAt(0)){
                    case '#':
                         document.getElementById(sub);
                        break;
                    case '.'if(context.getElementsByClassName)  context.getElementsByClassName(sub);
                        tagAll = Lazy.$('*');
                        n = tagAll.length;
                        for(i = 0;i<n;i++){
                            if(tagAll[i].className.indexOf(sub) > -1) eles.push(tagAll[i]);
                        }
                         eles;
                        default context.getElementsByTagName(arg);
                        ;
                }
            }
        },getPos: (node) {
            var scrollx = document.documentElement.scrollLeft || document.body.scrollLeft,scrollt = document.documentElement.scrollTop || document.body.scrollTop;
            var pos = node.getBoundingClientRect();
            return {top:pos.top + scrollt,right:pos.right + scrollx,bottom:pos.bottom + scrollt,left:pos.left + scrollx }
        },bind:(node,type,handler){
            node.addEventListener?node.addEventListener(type,handler,1)">false):node.attachEvent('on'+ type,handler);
        },unbind:false):node.detachEvent('on'+(eles){
            var arr = [];
            for(var i=0,n=eles.length;i<n;i++){
                arr.push(eles[i]);
            }
             arr;
        }
    };
     imgLazyLoad(){
        var timer,screenHeight = document.documentElement.clientHeight;
         选择所有图片
        var allimg = Lazy.$('img' 筛选CLASS为lazyload的图片
        var elems = Lazy.$('.lazyload' 转换为真正的数组
        elems = Lazy.toArray(elems);
        if(!elems.length) ;
         没有发生滚动事件时如果图片在可视范围之内,也显示
        var i = 0;i < elems.length;i++){
             获取图像的父元素即包裹图像的元素,判断图像是否在可视区域即直接判断父元素是否可视
            var parent = elems[i].parentNode;
             Lazy.getPos(parent);
            var posT = pos.top;
            var posB = pos.bottom;
             没有滚动条情况如果距离顶部的距离小于屏幕的高度则赋值SRC
            if(posT < screenHeight){
                elems[i].src = elems[i].getAttribute('data-img');
                 移除后,数组的长度减一,下一个下标需减一
                elems.splice(i--,1);
            }
        }
         绑定scroll事件
        Lazy.bind(window,'scroll' loading(){
            timer && clearTimeout(timer);
            timer = setTimeout((){
                var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                screenHeight = document.documentElement.clientHeight;
                ){
                     elems[i].parentNode;
                     Lazy.getPos(parent);
                     pos.top;
                     pos.bottom;
                    var screenTop = screenHeight+scrollTop;
                     元素顶部出现在可视区  或者  元素底部出现在可视区
                    if((posT > scrollTop && posT <  screenTop) || (posB > scrollTop && posB < screenTop)){
                        elems[i].src = elems[i].getAttribute('data-img');
                        elems.splice(i--,1)">);
                    }{
                         去掉以下注释开启图片预加载
                         new Image().src = elems[i].getAttribute('data-img');
                    }
                }
                if(!elems.length){
                    Lazy.unbind(window,'scroll');
        }
    }
    imgLazyLoad();

使用方法

1、在图片上增加lazyload的类(class='lazyload')

2、把真实的图片地址放入自定义属性data-img 中,把图片的SRC属性设置为一个一像素的透明图片,图片需要设置width,height属性,以免布局混乱

如下:

data-img="a.jpg" src="loading.gif" height="480"   class='lazyload'>

3、在需要延迟加载的页面调用imgLazyLoad()函数;

该原生js实现的懒加载转载地址:http://www.cnblogs.com/NNUF/archive/2012/06/25/2561570.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1.第一步 设置响应头 header(&#39;Access-Control-Allow-Origin:*&#39;); //支持全域名访问,不安全,部署后需要固定限制为客户端网址 header(&#39;Access-Control-Allow-Methods:POST,GET,OPTIONS,D
$.inArray()方法介绍 $.inArray()函数用于在数组中搜索指定的值,并返回其索引值。如果数组中不存在该值,则返回-1; $.inArray(value,array) --value是要查找的值,array是被查找的数组。 有如下实例: &lt;!DOCTYPE html&gt; &l
jquery.serializejson.min.js的妙用 关于这个jquery.serializejson.min.js插件来看,他是转json的一个非常简单好用的插件。 前端在处理含有大量数据提交的表单时,除了使用Form直接提交刷新页面之外,经常碰到的需求是收集表单信息成数据对象,Ajax提
JS 将form表单数据快速转化为object对象(json对象) jaymou 于 2020-03-03 11:11:05 发布 3534 收藏 3 分类专栏: 前端 文章标签: javascript jquery 版权 前端 专栏收录该内容 5 篇文章0 订阅 订阅专栏 直接上代码 /** *
jQuery的区别:$().click()和$(document).on(&#39;click&#39;,&#39;要选择的元素&#39;,function(){})的不同 文章地址:https://www.cnblogs.com/sqh17/p/7746418.html 解决:动态创建的元素的事件
jQuery插件之jquery.spinner数字智能增减插件 参考地址:http://www.helloweba.com/view-blog-282.html 左右加减数字 像京东提交订单时目前使用的是左右加减数字的效果,这个效果直接明了,操作简单。我们使用jquery.spinner.js插件实
layui标签或一般标签均可&lt;div class=&quot;layui-form-item&quot;&gt; &lt;label class=&quot;layui-form-label&quot;&gt;异地仓名称&lt;/label&gt; &lt;div class=&quot;la
网上对于select option 动态添加修改如下, $(&quot;#selectId&quot;).append(&quot;&lt;option value=&#39;&quot;+value+&quot;&#39;&gt;&quot;+text+&quot;&lt;/option&gt;&
jQuery中的 $.extend() 和 $.fn.extend() ANGWH 于 2020-05-24 06:39:59 发布 注意:$.extend是为jQuery类添加添加类方法,用$.调用(类似$.ajax),$.fn.extend则是为jQuery对象添加方法(实例方法),用DOM元素
jquery 循环数组输出显示在html页面 jquery 没有双向数据绑定,但是很多需求确实需要我们从后台接收到数组或者对象循环显示在前台页面上,这时我们可以用字符串拼接,元素添加的方法去实现 js部分如下: 复制代码 $(function(){ var a=[&quot;1aa&quot;,&q
javascript事件委托理解,jQuery .on()方法一步到位实现事件委托 Javascript-概念原理 专栏收录该内容 10 篇文章0 订阅 订阅专栏 本篇文章借鉴自:博客园文章,只为自己巩固下事件委托方面的知识 概述: 什么叫事件委托?他还有一个名字叫做事件代理,(时间代理 事件委托,
JQuery-$.when().done().fail()的使用 原文引用于&#160;Echoo华地于&#160;2022-01-06 14:07:10 发布 jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本。 每个版本都会引入一些新功能。今天我想介绍的,就是从jQuery 1
jQuery tableExport导出 excel 上篇写的是jQuery&#160;导出word,就试试导出excel。看见网上写的很乱,我这就把我写的整理下来,有部分来自网上capy 1. js文件的引用 &lt;script type=&quot;text/javascript&quot;
jQuery的遍历-prev()和next()方法 &lt;div class=&quot;box&quot; id=&quot;box&quot;&gt; &lt;a href=&#39;#&#39; class=&quot;a&quot;&gt; &lt;input type=&quot;tex
attr()和addClass()的区别 方法 addClass() attr()用途&#x9;追加样式&#x9;设置样式对同一个网页元素操作&#x9;&lt;p&gt;test&lt;/p&gt;第1次使用方法&#x9;$(&quot;p&quot;).addClass(&quot;high&quot;);&#x9;$(&quot;p&
前端——函数(匿名函数、自执行函数) FreshLemon_ 于 2019-06-11 17:11:49 发布 函数声明:function box(){} 函数表达式:var box = function(){}; 匿名函数:function(){} (属于函数表达式) 1声明了一个函数: var
js: 获取标签元素data-*属性值的方法 彭世瑜 于 2022-05-23 09:59:50 发布 2165 收藏 1 文章标签: javascript 前端 jquery 版权 标签上有两个属性data-id 和 data-user-name, 需要通过js去获取 &lt;style&gt;
JavaScript函数详解:匿名函数、具名函数、函数传参、不定参、返回值、JS预解析机制 1.具名函数 定义: 调用: 方式1:方法名(); 可以多次调用 方式2:在事件中调用,直接写函数名,不需用括号 2.匿名函数 没有名字的函数 匿名函数在使用时只有两种情况: 1.匿名函数自执行:声明后不需要
如何等待ajax完成再执行相应操作 ajax广泛应用于异步请求,对于大多数业务来说,这是十分方便的,但对于一些特殊的业务,ajax的异步性会起到相反的作用。 例如在ajax请求成功后,后续的操作需要依赖ajax执行成功后的相应操作。 // 声明一个表示状态的全局变量 status var statu
一步一步教你写一个jQuery的插件教程(Plugin) 更新时间:2009年09月03日 02:10:54 作者: 我将会在下面的例子中一个一个的说明上面这几个条件,做完这些事情后我们就会创建一个高亮显示text的简单插件。 jQuery 的plugin开发需要注意的事情, 1. 明确jQuery