图片懒加载
0. 前言
懒加载技术(简称lazyload)并不是新技术,它是js程序员对网页性能优化的一种方案。lazyload的核心是按需加载。在大型网站中都有lazyload的身影,例如谷歌的图片搜索页,迅雷首页,淘宝网,QQ空间等。因此掌握lazyload技术是非常重要的。
1.应用场合
涉及到多图片,falsh资源,iframe,网页编辑器(类似FCK)等占用较大带宽,且这些模块暂且不在浏览器可视区内,因此可以使用lazyload在适当的时候加载该类资源。避免网页打开时加载过多资源,让用户等待太久。
所谓的按需加载,一般我们用的比较多的是滚动加载方式。
2.实现原理及概念
lazyload的难点在于如何在适当的时候加载用户需要的资源(一般指的是用户需要的资源呈现在浏览器的可视区域)。 我们需要的一般是:
NOTE: documentElement是文档根节点,如果<HTML>元素缺失就返回null.
- 可视区域相对于浏览器顶端的位置
- 待加载资源相对于浏览器顶端的位置
我们来看几个常用的尺寸和距离相关的参数:
2.1 屏幕可视窗口大小.
对应于图中1 ,2位置处:
1. window.innerHeight/window.innerWidth 标准浏览器标准模式
2. document.documentElement.clientHeight 低版本IE标准模式
3. document.body.clientHeight
低版本IE混杂模式
屏幕可视窗口大小(视口) 就是 元素document.documentElement这个的clientXXX 即内部空间大小!
简便:
var height=document.documentElement.clientHeight||document.body.clientHeight;
完整兼容版:
function getViewport(w){
w=w||window;
//除了IE8以及之前的版本,其他都能用
if(w.innerWidth!=null) return {
width:w.innerWidth,
height:w.innerHeight
};
var d=w.document;
//怪异模式
if(d.compatMode=='BackCompat'){
return {
width:d.body.clientWidth,
height:d.body.clientHeight
};
}else{
//标准模式
return{ //CSS1Compat
width:d.documentElement.clientWidth,
height:d.documentElement.clientHeight
};
}
}
2.2 浏览器窗口顶部于文档顶部之间的距离
也就是滚动条滚动的距离!图中3,4处对应位置
window.pageYoffset/window.pageXoffset IE9+标准模式
document.documentElement.scrollTop 兼容低版本IE的标准模式
document.body.scrollTop 兼容混杂模式
实际代码:
var scrollTop=document.body.scrollTop||document.documentElement.scrollTop;
获取元素的位置
对应图中7、8的位置
jQuery:
$(o).offset().top 元素距离文档顶的距离
$(o).offset().left 元素距离文档左边缘的距离
原生:
getElementLeft() 同上 ,获取元素距离左边缘的距离
这个函数获取了位置。 兼容所有浏览器~
function getElementLeft(element){
var actualLeft=element.offsetLeft;
var current=element.offsetParent;
while(current!==null){
actualLeft+=current.offsetLeft;
curret=current.offsetParent;
}
}
getElementTop() 距离顶部最边缘的距离
这两个函数利用offsetParent 属性在DOM层次中逐级向上回溯,将每个层次中的偏移量属性合计到一起。
优劣:
对于简单的CSS布局页面可以得到精确结果。
但是对于表格和内嵌iframe的页面,得到的值就不精确了,
一般来说
页面中的所有元素都会被包含在几个div元素中,而这些div元素的offsetParent又是body元素,所以getElementLeft() getElementTop()与 offsetLeft offsetTop会返回相同的值。
获取元素的尺寸
对应图5,6位置处。
o.style.width
o.style.height
这种是内联样式。不一定是已经有内嵌的样式了。
eg: <div style="width:100%"></div>
外部或内部样式表的CSS样式的话,必须使用
o.currentStyle[xxx]||document.defaultView.getComputedStyle(0)[xxx] 来获取样式值!
3 概念解释
clientWidth or clientHeight 内部空间大小是被称为客户区大小client dimension。 它指的是元素内容及其内边距所占据的空间大小。
仅仅是 :内容+内边距padding
即不包括边框也不包括滚动条!
因为客户区大小就是元素内部空间大小。 最常用到的就是document.documentElement.clientHeight 或
document.body.clientHeight 表示的是浏览器的当前可视窗口大小!
clientLeft 和 clientTop边框宽度!
这个两个值一般返回的是 元素的 内边距的外边缘和边框外边缘(没有边框就是外边距内边缘)。
通常就等于left boder 和 top border的宽度,边框宽度
但是如果有滚动条,那就包含了滚动条的宽度!
note:对于内联元素来说,这两个值永远是0
元素位置 偏移量 offsetXXX: 包括元素在屏幕上占用的所有可见的空间。 元素可见大小由其高度、宽度决定,包括所有内边距,滚动条和边框大小。
元素位置 offsetXXX
- 为什么不使用o.style.top o.style.left? 这个属性其实是有问题的,它必须是position:absolute绝对定位后,设置 top left 这些属性才有效果~
- 这个是包含了所有内边距,滚动条和边框大小,不包括外边距。
offsetHeight: 元素在垂直方向占用空间大小,包括了元素高度,可见水平滚动条的高度,上边框和下边框高度。
offsetWidth:元素的水平方向上占用的空间大小,包括元素的宽度,可见垂直滚动条的宽度,左右边框的宽度。
offsetLeft: 元素的左外边框至包含元素(父元素)的左内边框之间的像素距离
offsetTop: 元素的上外边框至包含元素(父元素)的上内边框之间的像素距离
offsetWidth/Height
元素尺寸的一种:
offsetWidth 和 offsetHeight =内容+padding+border
是任何HTML元素的只读属性,返回屏幕尺寸!
包括内容、边框和内边距!!!!
offsetLeft/Top
这两个属性返回元素的X和Y坐标,这些值是文档坐标,直接指定元素的位置! 对于定位元素来说,是返回相对祖先元素(position:relative) 的坐标。
offsetParent属性指定了这些元素的相对父元素。
如果offsetParent==null,这些属性就是文档坐标了。
- 另外一个问题,其实是style是内联样式,它和你在CSS设置的样式不一样! 你在css中设置了样式不代表内联样式中就有,它是没有的!
p{
position:absolute;
left:100px;
top:200px;
}
pItem.style.left
pItem.style.top 是没有值的!
style
任何支持style特性的HTML元素在js中都有一个对应的style属性。这个style对象是CSSStyleDeclaration实例,包含通过HTML的style特性指定的所有样式信息,但是不包含外部样式表或嵌入样式表层叠而来的样式!
var div=document.getElementById('xxx');
div.style.cssText='border:2px dashed green;color:red;'; //这个修改或读取的是内联样式!
div.className='classA'; //这个修改的是 外部样式
scrollHeight/scrollWidth**滚动大小**
其实为什么要有这个属性呢,主要原因是:
因为实际内容可能比视口大,就需要把元素的滚动条位置考虑进去~
因为HTML元素的实际内容可能比分配用来容纳内容的盒子更大!
内容区域是视口,即浏览器的窗口!
滚动大小
指的是包含滚动内容的元素的大小。
对于滚动: 滚动不是所有元素
<html>元素是没有执行任何代码也能自动添加滚动条的;
但另外一些元素,则需要通过CSS的overflow属性进行设置才能滚动。
定义:
- scrollHeight 在没有滚动条情况下,元素内容的总高度。
- scrollWidth 在没有滚动条的情况下,元素内容的总宽度
- scrollLeft 被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。(水平)
- scrollTop 被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置
(垂直)
scrollWidth/Height=元素的内容区域+ 内边距padding+溢出尺寸
scrollWidth 和 scrollHeight主要用于确定元素内容的实际大小。通常认为html元素是在web浏览器的视口中滚动的元素。(IE6混杂模式是body)
所以最正常来说 和clientWidth/Height的区别就是在有滚动条的时候啦!
因此带有垂直滚动条的页面总高度就是:
document.documentElement.scrollHeight
但是对于不包含滚动条的页面:
scrollWidth,scrollHeight和 clientWidth clientHeight的关系并不十分清晰。
(通过document.documentElement查看)
- FF中这两组值始终相同
- Opera Safari 及更高版本,Chrome中这两组属性是不同,scrollXXX是视口(viewport)大小,clientXXX是文档内容区域大小。
- IE中,则跟上面的反过来,clientXX是视口,而scrollXXX是文档内容区域
确定文档的总高度(这是没有滚动条的情况)!
var docHeight=Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);
var docWidth=Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);
有滚动条的时候:
document.documentElement.scrollHeight 代表了整个文档的总高度(包括了隐藏的内容,因为滚动条)
document.documentElement.clientHeight 则仅仅是可见内容,即视口
scrollTop&&scrollLeft
scrollTop 则表示元素上方不可见内容的像素高度
scrollLeft 表示元素左侧不可见内容的像素宽度
指定了元素滚动条的位置。我们可以通过这两个属性获取到窗口的滚动条的位置,即滚动条的偏移量~ 通过检测这个变化就能滚动加载。
元素大小
js高程中,使用的是getBoundingClientRect
IE, FF,Safari ,Opera 以及Chrome为每个元素都提供了一个getBoundingClientRect()方法。这个方法返回一个矩形对象,包含:
left , top, right,bottom
意义:
这些属性给出了元素在页面中相对于视口的位置。 但是浏览器的实现稍有不同。IE8及更早认为(2,2)是左上角的坐标。 而其他浏览器包括IE9则将传统(0,0)作为起点坐标。
JS高程中给出了一个跨浏览器的函数,来获取相同的信息。也就是元素的尺寸以及位置
Note :
客户区大小(元素内部的空间大小),和偏移量都是只读的。 每次访问会重新计算。