本文使用的lazyload版本是1.9.7,戳我下载该版本
先来看看懒加载元素与懒加载视口的关系。什么是视口呢?视口是指图片可加载区域,在视口范围内,懒加载元素的图片可能已经加载完或即将加载或正在加载以渲染给用户看。那么元素与视口与有怎样的关系呢?看下面1~4
1、元素出现在视口下方
设fold为屏幕的高度、页面滚动scrollTop、threshold 之和,它与懒加载元素的顶部偏移量Y进行比较。
fold =
window.height()+
window.scrollTop() + settings.threshold;
Y =
(element).offset().top;fold大于Y说明该元素从视口下方进入(退出)视口,
.belowthefold返回值为false,如果是进入要开始对该元素的图片进行加载。
fold小于Y 说元素不在视口范围内,则$.belowthefold 值为true。
参考图1进行代码理解。
$.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;
};
2、元素出现在视口上方
设fold为页面滚动scrollTop、threshold 之差,它与懒加载元素的底部位置Y进行比较。
fold =
window.scrollTop()−settings.threshold;Y=
(element).offset().top +
(element).height();fold小于Y说明该元素从视口下方进入(退出)视口,
.abovethetop 返回值为false。如果是进入就要开始对该元素的图片进行加载。
fold大于Y 说明元素不在视口范围内,$.abovethetop 值为true。
参考图2进行代码理解。
$.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();
};
3、元素出现在视口上方
设fold为页面滚动scrollLeft、threshold 之差,它与某元素的左部位置X进行比较。
fold =
window.scrollLeft()−settings.threshold;X=
(element).offset().left +
(element).width();fold小于X说明该元素从视口左方进入(退出)视口,
.leftofbegin 返回值为false。如果是进入就要开始对该元素的图片进行加载。
fold大于X 说明该元素不在视口范围内,则$.leftofbegin 返回值为true。
参考图3进行代码理解。
$.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();
};
4、元素在视口右方
设fold为页面滚动scrollLeft、threshold 之差,它与某元素的左部位置X进行比较。
fold =
window.width()+
window.scrollLeft() + settings.threshold;
X =
(element).offset().left;fold大于X说明该元素从视口右方进入(退出)视口,
.rightoffold返回值为false。如果是进入就要开始对该元素的图片进行加载。
fold小于X 说明该元素不在视口范围内,$.rightoffold 返回值为true。
参考图3进行代码理解。
$.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;
};
5、总结
如果懒加载元素出现在视口上方,也出现在是否下方,说明懒加载元素竖直方向已被视口所包裹,即竖直方向,懒加载元素在视口内。
如果懒加载元素出现在视口左方,也出现在是否右方,说明懒加载元素水平方向已被视口所包裹,即水平方向,懒加载元素在视口内。
如果懒加载元素出现在视口上、下、左、右方内,那么该元素就在视口内。
6、为元素加载图片
this.each(function() {
var self = this;
var $self = $(self);
self.loaded = false;
/* 图片元素没有src属性时,设置其src为默认背景色或图片 */
if ($self.attr("src") === undefined || $self.attr("src") === false) {
if ($self.is("img")) {
$self.attr("src", settings.placeholder);
}
}
/* 为每个元素加载原始图片 */
$self.one("appear", function() {
if (!this.loaded) {
if (settings.appear) {
var elements_left = elements.length;
settings.appear.call(self, elements_left, settings);
}
$("<img />")
.one("load", function() {
var original = $self.attr("data-" + settings.data_attribute);
$self.hide();
//如果是图片元素则设置src属性,不然则设置为背景图片
if ($self.is("img")) {
$self.attr("src", original);
} else {
$self.css("background-image", "url('" + original + "')");
}
$self[settings.effect](settings.effect_speed);
self.loaded = true;
/* 将该元素从数组移除,它将不再执行appea事件. */
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.on(settings.event, function() {
if (!self.loaded) {
$self.trigger("appear");
}
});
}
});
7、何时停止懒加载的执行呢?
当存在settings.failure_limit个元素, 不在视口上方左方范围内,那么停止。
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;
}
}
});
}
//这里其实还不是很明白。
写了个大概,还有些细节没弄懂,弄懂再补上。