在專案中有時候會用到圖片的延遲加載,那麼延遲加載的好處是啥呢?
我覺得主要包括兩點吧,第一是在包含很多大圖片長頁面中延遲加載圖片可以加快頁面加載速度;第二是幫助降低伺服器負擔。
下面介紹常用的延遲載入外掛jquery.lazyload.js以及怎麼實作一個延遲載入的外掛。
lazyload是jQuery寫的延遲加載插件,在瀏覽器可視區域外的圖片不會被載入, 直到用戶將頁面滾動到它們所在的位置. 這與圖片預先載入的處理方式正好是相反的。
首先選取的img元素都綁定了一個appear事件(處理img顯示真實的圖片位址),方便以後滿足條件時觸發該事件;
在配置物件中有一個container屬性配置,預設為window,如果img元素在該container容器視口中,則觸發appear事件;
為了判斷img元素是否在container容器視口範圍中,有如下四個方法:
$.belowthefold = function(element, settings) {}; // 在视口下方$.rightoffold = function(element, settings) {}; // 在视口右方$.abovethetop = function(element, settings) {}; // 在视口上方$.leftofbegin = function(element, settings) {}; // 在视口左方
由於延遲載入lazyload是依賴jquery的,所有頁面需要引入jquery,如下:
<script src="jquery.js?1.1.11"></script><script src="jquery.lazyload.js?1.1.11"></script>
基本寫法:
<img class="lazy" data-original="img/example.jpg" width="640" height="480">$(function() { $("img.lazy").lazyload(); });
其中的data-original 屬性存放真實的圖片url路徑。
小貼士:你必須設定圖片的寬度或高度在css中,否則外掛程式可能無法正常運作。
預設圖片會出現在螢幕時載入. 如果你想提前載入圖片, 可以設定threshold 選項, 設定threshold 為200 令圖片在距離畫面200像素時提前載入。
$("img.lazy").lazyload({ threshold : 200});
事件可以是任何jQuery 事件, 如: click 和mouseover. 你也可以使用自訂的事件, 如: sporty 和foobar . 預設情況下處於等待狀態, 直到使用者滾動到視窗上圖片所在位置. 在灰色佔位圖片被點擊之前阻止載入圖片, 你可以這樣做:
$("img.lazy").lazyload({ event : "click"});
當然,你也可以用下面的這種方式實現延遲載入:
$(function() { $("img.lazy").lazyload({ event : "sporty"}); }); $(window).bind("load", function() {var timeout = setTimeout(function() { $("img.lazy").trigger("sporty") }, 5000); });
即是頁面載入完成5 秒後,再去執行圖片的懶載入。
當圖片完全載入的時候, 外掛預設地使用show() 方法來將圖顯示出來. 其實你可以使用任何你想用的特效來處理. 下面的程式碼使用FadeIn 效果:
$("img.lazy").lazyload({ effect : "fadeIn"});
幾乎所有瀏覽器的JavaScript 都是啟動的. 然而可能你仍希望能在不支援JavaScript 的客戶端展示真實圖片. 當瀏覽器不支援JavaScript 時優雅降級, 你可以將真實的圖片片段在寫
<img class="lazy" data-original="img/example.jpg" width="640" heigh="480"><noscript><img src="img/example.jpg" width="640" heigh="480"></noscript>
可以透過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});
官網位址:
/*! * Lazy Load - jQuery plugin for lazy loading images * * Copyright (c) 2007-2015 Mika Tuupola * * Licensed under the MIT license: * * * Project home: * * * Version: 1.9.7 * */ (function($, window, document, undefined) {var $window = $(window); $.fn.lazyload = function(options) {var elements = this;var $container;var settings = { threshold : 0, failure_limit : 0, event : "scroll", effect : "show", container : window, data_attribute : "original", skip_invisible : false, appear : null, load : null, placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"}; function update() {var counter = 0; elements.each(function() {var $this = $(this);if (settings.skip_invisible && !$this.is(":visible")) {return; }if ($.abovethetop(this, settings) ||$.leftofbegin(this, settings)) {/* Nothing. */} else if (!$.belowthefold(this, settings) && !$.rightoffold(this, settings)) { $this.trigger("appear");/* if we found an image we'll load, reset the counter */counter = 0; } else {if (++counter > settings.failure_limit) {return false; } } }); } if(options) {/* Maintain BC for a couple of versions. */if (undefined !== options.failurelimit) { options.failure_limit = options.failurelimit;delete options.failurelimit; }if (undefined !== options.effectspeed) { options.effect_speed = options.effectspeed;delete 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, function() {return update(); }); } this.each(function() {var self = this;var $self = $(self); self.loaded = false; /* If no src attribute given use data:uri. */if ($self.attr("src") === undefined || $self.attr("src") === false) {if ($self.is("img")) { $self.attr("src", settings.placeholder); } } /* When appear is triggered load original image. */$self.one("appear", function() {if (!this.loaded) {if (settings.appear) {var elements_left = elements.length; settings.appear.call(self, elements_left, settings); } $("<img />") .bind("load", function() { var original = $self.attr("data-" + settings.data_attribute); $self.hide();if ($self.is("img")) { $self.attr("src", original); } else { $self.css("background-image", "url('" + original + "')"); } $self[settings.effect](settings.effect_speed); self.loaded = true; /* Remove image from array so it is not looped next time. */var temp = $.grep(elements, function(element) {return !element.loaded; }); elements = $(temp); if (settings.load) {var elements_left = elements.length; settings.load.call(self, elements_left, 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, function() {if (!self.loaded) { $self.trigger("appear"); } }); } }); /* Check if something appears when window is resized. */$window.bind("resize", function() { 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", function(event) {if (event.originalEvent && event.originalEvent.persisted) { elements.each(function() { $(this).trigger("appear"); }); } }); } /* Force initial check if images should appear. */$(document).ready(function() { update(); }); return this; }; /* Convenience methods in jQuery namespace. *//* Use as $.belowthefold(element, {threshold : 100, container : window}) */ $.belowthefold = function(element, settings) {var fold; if (settings.container === undefined || settings.container === window) { fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop(); } else { fold = $(settings.container).offset().top + $(settings.container).height(); } return fold <= $(element).offset().top - settings.threshold; }; $.rightoffold = function(element, settings) {var fold; if (settings.container === undefined || settings.container === window) { fold = $window.width() + $window.scrollLeft(); } else { fold = $(settings.container).offset().left + $(settings.container).width(); } return fold <= $(element).offset().left - settings.threshold; }; $.abovethetop = function(element, settings) {var fold; if (settings.container === undefined || settings.container === window) { fold = $window.scrollTop(); } else { fold = $(settings.container).offset().top; } return fold >= $(element).offset().top + settings.threshold + $(element).height(); }; $.leftofbegin = function(element, settings) {var fold; if (settings.container === undefined || settings.container === window) { fold = $window.scrollLeft(); } else { fold = $(settings.container).offset().left; } return fold >= $(element).offset().left + settings.threshold + $(element).width(); }; $.inviewport = function(element, settings) { 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" : function(a) { return !$.belowthefold(a, {threshold : 0}); },"right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); },"left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); },"in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); },/* Maintain BC for couple of versions. */"above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); },"right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); },"left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); } }); })(jQuery, window, document);
#js程式碼
window.smallDelay = (function(window, document, undefined) {'use strict';var store = [],poll;var settings = { offset:0, //离可视区域多少像素的图片可以被加载throttle: 250 //图片延时多少毫秒加载 } var _inView = function(el) {var coords = el.getBoundingClientRect();return ((coords.top >= 0 && coords.left >= 0) && coords.top <= ((window.innerHeight || document.documentElement.clientHeight) + parseInt(settings.offset))); };var _pollImages = function() {for (var i = store.length; i--;) {var self = store[i];if (_inView(self)) { self.src = self.getAttribute('data-delay'); store.splice(i, 1); } } };var _throttle = function() { clearTimeout(poll); poll = setTimeout(_pollImages, settings.throttle); };var init = function(obj) {var nodes = document.querySelectorAll('[data-delay]');var opts = obj || {}; settings.offset = opts.offset || settings.offset; settings.throttle = opts.throttle || settings.throttle;for (var i = 0; i < nodes.length; i++) { store.push(nodes[i]); } _throttle(); //滚动监听执行图片懒加载if (document.addEventListener) { window.addEventListener('scroll', _throttle, false); } else { window.attachEvent('onscroll', _throttle); } //返回该对象进行链式操作return this; };return { init: init, render: _throttle }; })(window, document);
呼叫方式:
smallDelay.init({ offset: 0,//离可视区域多少像素的图片可以被加载 throttle: 0 //图片延时多少毫秒加载});
html程式碼:
##<img src="images/loading.gif" data-delay="images/avatar.png" />
1、增加了图片预加载可选
2、修改了图片本身就在可视范围的时候直接显示而不需要滚动条触发
3、修改了Splice删除数组的时候,会跳过下一张图片BUG
4、浏览器窗口resize的时候图片出现也会加载
5、判断图片父层包裹顶部或者底部出现在可视范围内即可显示图片
var Lazy = { $:function(arg,context){var tagAll,n,eles=[],i,sub = arg.substring(1); context = context|| document;if(typeof arg =='string'){switch(arg.charAt(0)){case '#':return document.getElementById(sub);break;case '.':if(context.getElementsByClassName) return 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]); }return eles;break;default:return context.getElementsByTagName(arg);break; } } }, getPos:function (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:function(node,type,handler){ node.addEventListener?node.addEventListener(type, handler, false):node.attachEvent('on'+ type, handler); }, unbind:function(node,type,handler){ node.removeEventListener?node.removeEventListener(type, handler, false):node.detachEvent('on'+ type, handler); }, toArray:function(eles){var arr = [];for(var i=0,n=eles.length;i<n;i++){ arr.push(eles[i]); }return arr; } };function imgLazyLoad(){var timer,screenHeight = document.documentElement.clientHeight;// 选择所有图片var allimg = Lazy.$('img');// 筛选CLASS为lazyload的图片var elems = Lazy.$('.lazyload',allimg);// 转换为真正的数组elems = Lazy.toArray(elems);if(!elems.length) return;// 没有发生滚动事件时如果图片在可视范围之内,也显示for(var i = 0;i < elems.length;i++){// 获取图像的父元素即包裹图像的元素,判断图像是否在可视区域即直接判断父元素是否可视var parent = elems[i].parentNode;var pos = Lazy.getPos(parent);var posT = pos.top;var posB = pos.bottom;// 没有滚动条情况如果距离顶部的距离小于屏幕的高度则赋值SRCif(posT < screenHeight){ elems[i].src = elems[i].getAttribute('data-img');// 移除后,数组的长度减一,下一个下标需减一elems.splice(i--,1); } }// 绑定scroll事件Lazy.bind(window,'scroll',loading); Lazy.bind(window,'resize',loading);function loading(){ timer && clearTimeout(timer); timer = setTimeout(function(){var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; screenHeight = document.documentElement.clientHeight;for(var i = 0;i < elems.length;i++){var parent = elems[i].parentNode;var pos = Lazy.getPos(parent);var posT = pos.top;var posB = 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); }else{// 去掉以下注释开启图片预加载// new Image().src = elems[i].getAttribute('data-img'); } }if(!elems.length){ Lazy.unbind(window,'scroll',loading); Lazy.unbind(window,'resize',loading); } },300); } } imgLazyLoad();
1、在图片上增加lazyload的类(class='lazyload')
2、把真实的图片地址放入自定义属性data-img 中,把图片的SRC属性设置为一个一像素的透明图片,图片需要设置width,height属性,以免布局混乱
如下:
<img data-img="a.jpg" src="loading.gif" width="640" height="480" class='lazyload'>
3、在需要延迟加载的页面调用imgLazyLoad()函数;
该原生js实现的懒加载转载地址:
以上是圖片的懶載入以及jquery.lazyload.js的使用實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!