html + js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
body, div, img {
margin: 0;
padding: 0
}
</style>
</head>
<body>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/001.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/002.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/003.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/004.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/005.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/006.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/007.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/008.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/009.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/010.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/011.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/012.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/013.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/014.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/015.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/016.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/017.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/018.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/019.jpeg" alt="范冰冰"/><br/>
<img src="images/default.jpg" realSrc="http://localhost:63342/tql/2/images/020.jpeg" alt="范冰冰"/><br/>
</body>
</html>
<script type="text/javascript" src="js/utils.js"></script>
<script type="text/javascript">
var oImgs = document.getElementsByTagName("img");
for (var i = 0; i < oImgs.length; i++) {
var oImg = oImgs.item(i);
oImg.posi = utils.getOffset(oImg).top + utils.getEleClientWidthAndHeightContainBorder(oImg).height;
}
window.onscroll = function () {
var oImgs = document.getElementsByTagName("img");
for (var i = 0; i < oImgs.length; i++) {
var oImg = oImgs.item(i);
//浏览器的底边距离body的高度 = 获取滚动条相对于文档顶部的偏移 + 文档可视区域高度
// browserBottom = document.documentElement.scrollTop(获取滚动条相对于文档顶部的偏移) + document.documentElement.clientHeight(文档可视区域高度)
var browserBottom = (document.documentElement.scrollTop || document.body.scrollTop) + (document.documentElement.clientHeight || document.body.clientHeight);
loadImg(oImg, browserBottom);
}
}
function loadImg(oImg, browserBottom) {
if (oImg.loaded) {
return;
}
if (oImg.posi < browserBottom) {
var tempImg = new Image();
var src = oImg.getAttribute("realSrc");
src = src + "?" + Math.random();
tempImg.src = src;
oImg.src = "images/loading.gif";
tempImg.onload = function () {
oImg.src = src;
oImg.loaded = true;
}
}
}
</script>
依赖 utils.js
/*工具包,单例模式*/
var utils = {
/*
listToArray:将类数组转化成数组,兼容所有浏览器
参数:listArray:类数组
用法:var ary = utils.listToArray(lis);
*/
listToArray: function (listArray) {
var ary = [];
try {
// 通过call方法改变slice中this的指向,克隆出类数组中的元素
ary = Array.prototype.slice.call(listArray, 0);
}
catch (e) {
//ie下...
// 循环把类数组中的元素放到数组中
for (var i = 0; i < listArray.length; i++) {
ary[ary.length] = listArray[i];
}
}
return ary;
},
/*
toJSON:把JSON格式字符串转换成JSON对象
参数:str JSON格式字符
用法:var obj = utils.toJSON(str);
* */
toJSON: function (str) {
/*if ("JSON" in window) {
return JSON.parse(str);
} else {
//ie 6 7
return eval("(" + str + ")");
}*/
return "JSON" in window ? JSON.parse(str) : eval("(" + str + ")");
},
/*
toJSONString:Json对象转字符串方法
参数:obj JSON对象
用法:var str = utils.toJSONString(obj);
* */
toJSONString: function (obj) {
var S = [];
for (var item in obj) {
obj[item] = typeof obj[item] == 'string' ? '"' + obj[item] + '"' : (typeof obj[item] == 'object' ? this.toJSONString(obj[item]) : obj[item]);
S.push(item + ':' + obj[item]);
}
return '{' + S.join(',') + '}';
},
/*
* avgFn1:输入一组数字求平均数,保留2位小数
* 参数:10, 10, 9, 8, 1...
* 用法:var avg = utils.avgFn1(10, 10, 9, 8, 1)
*/
avgFn1: function () {
//1.把arguments 类数组转换成数组
var ary = [];
for (var i = 0; i < arguments.length; i++) {
ary[ary.length] = arguments[i];
}
//2.给数组进行排序,然后去掉首尾
ary.sort(function (a, b) {
return a - b;
})
ary.shift(); //去首
ary.pop(); //去尾
//3.求和求平均
var total = null;
for (var i = 0; i < ary.length; i++) {
total += ary[i];
}
return (total / ary.length).toFixed(2);
},
/* 优化
* avgFn2:输入一组数字求平均数,保留2位小数
* 参数:10, 10, 9, 8, 1...
* 用法:var avg = utils.avgFn2(10, 10, 9, 8, 1)
*/
avgFn2: function () {
//1.把arguments 类数组转换成数组(用类数组转换成数组的优化)
/*var ary = [];
for (var i = 0; i < arguments.length; i++) {
ary[ary.length] = arguments[i];
}*/
var ary = Array.prototype.slice.call(arguments, 0);
//2.给数组进行排序,然后去掉首尾
ary.sort(function (a, b) {
return a - b;
}).shift(); //去首
ary.length--; //去尾
//3.求和求平均 优化
return (eval(ary.join("+")) / ary.length).toFixed(2);
},
/* 优化
* avgFn3:输入一组数字求平均数,保留2位小数
* 参数:10, 10, 9, 8, 1...
* 用法:var avg = utils.avgFn3(10, 10, 9, 8, 1)
*/
avgFn3: function () {
//1.把arguments 类数组转换成数组(用类数组转换成数组的优化)
/*var ary = [];
for (var i = 0; i < arguments.length; i++) {
ary[ary.length] = arguments[i];
}*/
var ary = Array.prototype.slice.apply(arguments, [0]);
//2.给数组进行排序,然后去掉首尾
ary.sort(function (a, b) {
return a - b;
}).shift(); //去首
ary.length--; //去尾
//3.求和求平均 优化
return (eval(ary.join("+")) / ary.length).toFixed(2);
},
/* 深度优化
* avgFn4:输入一组数字求平均数,保留2位小数
* 参数:10, 10, 9, 8, 1...
* 用法:var avg = utils.avgFn4(10, 10, 9, 8, 1)
*/
avgFn4: function () {
//类数组转成数组,在给数组进行排序
[].sort.call(arguments, function (a, b) {
return a - b;
});
[].shift.call(arguments); //去首
[].pop.call(arguments); //去尾
//求和求平均 优化
//console.info(arguments.length)
return (eval([].join.call(arguments, "+")) / arguments.length).toFixed(2);
},
/*
* regExec:正则捕获符合规则的所有结果,原理利用改变正则的懒惰性
* 参数:reg:正则表达式/g str 要捕获结果的字符串
* 用法:var ary = utils.regExec(reg,str)
*/
regExec: function (reg, str) {
var ary = [];
var res = reg.exec(str);
while (res) {
ary.push(res.shift());
res = reg.exec(str);
}
return ary;
},
/*
* strMatch:字符串捕获符合正则规则的所有结果
* 局限:当reg存在分组的情况下,str.match(reg)就无法处理了
* 参数:reg:正则表达式/g str 要捕获结果的字符串
* 用法:var ary = utils.strMatch(reg,str)
*/
strMatch: function (reg, str) {
var ary = str.match(reg);
return ary;
},
/*
* getCss:获取某个元素的某个具体css结果
* 参数:ele:元素 attr css属性名称
* 用法:var obj = utils.getCss(ele,attr)
*/
getCss: function (ele, attr) {
if (typeof getComputedStyle == "function") {
return getComputedStyle(ele, null)[attr];
} else {
//ie 6 7 8
return ele.currentStyle[attr];
}
},
/*
获取任意元素距离body的偏移,相对与document的偏移量
通过向上迭代offsetParent,可以计算出相对于document的偏移量,也就是相对与页面的偏移量。
此方法的问题:
1)对于使用表格和内嵌框架布局的页面,由于不同浏览器实现元素方式的差异,得到的结果就不精确了。
2)每次都需要一级一级向上查找offsetParent,效率太低。
*/
getOffsetSum: function (ele) {
var top = 0, left = 0;
while (ele) {
if (window.navigator.userAgent.indexOf("MSIE 8") > -1) {
top += ele.offsetTop;
left += ele.offsetLeft;
} else {
//在标准浏染器下要加上边框
top += ele.offsetTop + ele.clientTop; //ele.clientTop 是上边框的宽
left += ele.offsetLeft + ele.clientLeft; //ele.clientLeft 是左边框的宽
}
ele = ele.offsetParent;
}
return {
top: top,
left: left
}
},
/*
此方法直接通过getBoundingClientRect()方法获得相对于视口的偏移量,
加上页面的滚动量,减去clientTop,clientLeft (IE8及更低版本浏览器将(2,2)作为起点坐标,
所以要将值减去起点坐标,其他浏览器都是已(0,0)作为起点坐标)。
getBoundingClientRect()方法支持IE,ff3+,safari4+,Orear9,5,Chrome.
*/
getOffsetRect: function (ele) {
var box = ele.getBoundingClientRect();
var body = document.body,
docElem = document.documentElement;
//获取页面的scrollTop,scrollLeft(兼容性写法)
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop,
scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop || body.clientTop,
clientLeft = docElem.clientLeft || body.clientLeft;
var top = box.top + scrollTop - clientTop,
left = box.left + scrollLeft - clientLeft;
return {
//Math.round 兼容火狐浏览器bug
top: Math.round(top),
left: Math.round(left)
}
},
/*
* 获取任意元素距离body的偏移
* 对于支持getBoundingClientRect()方法的浏览器使用getOffsetRect()方法,不支持的则使用getOffsetSum()方法
* 参数:ele
* 用法:var obj = utils.getOffset(ele)
*/
getOffset: function (ele) {
if (ele.getBoundingClientRect) {
return this.getOffsetRect(ele);
} else {
return this.getOffsetSum(ele);
}
},
/*
* 获取任意元素距离父级元素的偏移
* 注意父级元素css要加上position
* 参数:ele
* 用法:var obj = utils.getRelativeOffset(ele)
*/
getRelativeOffset: function (ele) {
var top = ele.offsetTop;
var left = ele.offsetLeft;
return {
top: top,
left: left
}
},
/*
* getEleClientWidthAndHeight:计算元素本身的宽高
* 参数:ele:元素 包含元素的padding
* clientWidth,clientHeight:元素可视区域尺寸,内边距以内的减去滚动条自身尺寸后的尺寸,即padding + width(height) - 滚动条自身尺寸,
* 用法:var obj = utils.getEleClientWidthAndHeight(ele)
*/
getEleClientWidthAndHeight: function (ele) {
var w = ele.clientWidth;
var h = ele.clientHeight;
return {width: w, height: h}
},
/*
* getEleClientWidthAndHeightContainBorder:计算元素本身的宽高包含边框
* 参数:ele:元素 包含元素的padding
* offsetWidth,offsetHeight:元素包含边框以内的尺寸,包含滚动条自身尺寸,即border + padding + width(height),
* */
getEleClientWidthAndHeightContainBorder: function (ele) {
var w = ele.offsetWidth;
var h = ele.offsetHeight;
return {width: w, height: h}
}
};