Skip to content

Commit 37d74ae

Browse files
committed
image lazy load Library layzr demo
1 parent 771a51d commit 37d74ae

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

img-lazyload/layzr.js

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
(function(root, factory) {
2+
if(typeof define === 'function' && define.amd) {
3+
define([], factory);
4+
} else if(typeof exports === 'object') {
5+
module.exports = factory();
6+
} else {
7+
root.Layzr = factory();
8+
}
9+
}(this, function() {
10+
'use strict';
11+
12+
// CONSTRUCTOR
13+
14+
function Layzr(options) {
15+
// debounce
16+
this._lastScroll = 0;
17+
this._ticking = false;
18+
19+
// options
20+
options = options || {};
21+
22+
this._optionsSelector = options.selector || '[data-layzr]';
23+
this._optionsAttr = options.attr || 'data-layzr';
24+
this._optionsAttrRetina = options.retinaAttr || 'data-layzr-retina';
25+
this._optionsAttrBg = options.bgAttr || 'data-layzr-bg';
26+
this._optionsAttrHidden = options.hiddenAttr || 'data-layzr-hidden';
27+
this._optionsThreshold = options.threshold || 0;
28+
this._optionsCallback = options.callback || null;
29+
30+
// properties
31+
this._retina = window.devicePixelRatio > 1;
32+
this._srcAttr = this._retina ? this._optionsAttrRetina : this._optionsAttr;
33+
34+
// nodelist
35+
this._nodes = document.querySelectorAll(this._optionsSelector);
36+
37+
// call to create
38+
this._create();
39+
}
40+
41+
// DEBOUNCE HELPERS
42+
// adapted from: http://www.html5rocks.com/en/tutorials/speed/animations/
43+
44+
Layzr.prototype._requestScroll = function() {
45+
this._lastScroll = window.scrollY || window.pageYOffset;
46+
this._requestTick();
47+
};
48+
49+
Layzr.prototype._requestTick = function() {
50+
if(!this._ticking) {
51+
requestAnimationFrame(this.update.bind(this));
52+
this._ticking = true;
53+
}
54+
};
55+
56+
// OFFSET HELPER
57+
// borrowed from: http://stackoverflow.com/questions/5598743/finding-elements-position-relative-to-the-document
58+
59+
Layzr.prototype._getOffset = function(element) {
60+
var offsetTop = 0;
61+
62+
do {
63+
if(!isNaN(element.offsetTop)) {
64+
offsetTop += element.offsetTop;
65+
}
66+
} while(element = element.offsetParent);
67+
68+
return offsetTop;
69+
};
70+
71+
// LAYZR METHODS
72+
73+
Layzr.prototype._create = function() {
74+
// fire scroll event once
75+
this._requestScroll();
76+
77+
// bind scroll and resize event
78+
window.addEventListener('scroll', this._requestScroll.bind(this), false);
79+
window.addEventListener('resize', this._requestScroll.bind(this), false);
80+
};
81+
82+
Layzr.prototype._destroy = function() {
83+
// possibly remove attributes, and set all sources?
84+
85+
// unbind scroll and resize event
86+
window.removeEventListener('scroll', this._requestScroll.bind(this), false);
87+
window.removeEventListener('resize', this._requestScroll.bind(this), false);
88+
};
89+
90+
Layzr.prototype._inViewport = function(node) {
91+
// get viewport top and bottom offset
92+
var viewportTop = this._lastScroll;
93+
var viewportBottom = viewportTop + window.innerHeight;
94+
95+
// get node top and bottom offset
96+
var elementTop = this._getOffset(node);
97+
var elementBottom = elementTop + node.offsetHeight;
98+
99+
// calculate threshold, convert percentage to pixel value
100+
var threshold = (this._optionsThreshold / 100) * window.innerHeight;
101+
102+
// return if element in viewport
103+
return elementBottom >= viewportTop - threshold
104+
&& elementTop <= viewportBottom + threshold
105+
&& !node.hasAttribute(this._optionsAttrHidden);
106+
};
107+
108+
Layzr.prototype._reveal = function(node) {
109+
// get node source
110+
var source = node.getAttribute(this._srcAttr) || node.getAttribute(this._optionsAttr);
111+
112+
// set node src or bg image
113+
if(node.hasAttribute(this._optionsAttrBg)) {
114+
node.style.backgroundImage = 'url(' + source + ')';
115+
}
116+
else {
117+
node.setAttribute('src', source);
118+
}
119+
120+
// call the callback
121+
if(typeof this._optionsCallback === 'function') {
122+
// "this" will be the node in the callback
123+
this._optionsCallback.call(node);
124+
}
125+
126+
// remove node data attributes
127+
node.removeAttribute(this._optionsAttr);
128+
node.removeAttribute(this._optionsAttrRetina);
129+
node.removeAttribute(this._optionsAttrBg);
130+
node.removeAttribute(this._optionsAttrHidden);
131+
};
132+
133+
Layzr.prototype.updateSelector = function() {
134+
// update cached list of elements matching selector
135+
this._nodes = document.querySelectorAll(this._optionsSelector);
136+
};
137+
138+
Layzr.prototype.update = function() {
139+
// cache nodelist length
140+
var nodesLength = this._nodes.length;
141+
142+
// loop through nodes
143+
for(var i = 0; i < nodesLength; i++) {
144+
// cache node
145+
var node = this._nodes[i];
146+
147+
// check if node has mandatory attribute
148+
if(node.hasAttribute(this._optionsAttr)) {
149+
// check if node in viewport
150+
if(this._inViewport(node)) {
151+
// reveal node
152+
this._reveal(node);
153+
}
154+
}
155+
}
156+
157+
// allow for more animation frames
158+
this._ticking = false;
159+
};
160+
161+
return Layzr;
162+
}));

img-lazyload/lazyload.html

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>无标题文档</title>
6+
<style>
7+
.border {
8+
padding: 10px;
9+
border-style: solid;
10+
border-width: 3px;
11+
border-color: blue;
12+
}
13+
</style>
14+
<script src="layzr.js"></script>
15+
</head>
16+
17+
<body>
18+
<!--http://callmecavs.github.io/layzr.js/--->
19+
<img data-layzr="https://www.baidu.com/img/bd_logo1.png"><br>
20+
<img data-layzr="http://www.zhinengshe.com/images/logo.png">
21+
<script>
22+
var layzr = new Layzr({
23+
selector: '[data-layzr]',
24+
callback: function () {
25+
console.log(this);
26+
this.classList.add('border');
27+
}
28+
});
29+
</script>
30+
31+
</body>
32+
</html>

0 commit comments

Comments
 (0)