LazyLoad(II) 实现及相关原理

0 . 文档和视口

元素的X和Y坐标可以相对于文档的左上角或相对于其中显示文档的视口的左上角。

文档坐标 和 大小

文档坐标在滚动的时候是不会改变的,它是X和Y坐标的绝对值,是包括了不可见的内容。

文档的大小
我指的是根文档document.documentElement 的宽度和高度。这个一般是

document.documentElement.scrollWidth
document.documentElement.scrolllHeight

它是不会随滚动条改变的!


视口坐标 和大小

视口坐标是减去了滚动条偏移量的坐标。代表了可见的当前窗口坐标。

视口的大小
视口的大小一般是:
getViewportSize()来决定,一般认为是

document.documentElement.clientWidth document.documentElement.clientHeight

1.滚动查询

window.scrollTo()
window.scroll()
这两个方法接收一个点的 X,Y坐标(文档坐标)并作为滚动条的偏移量设置它们:

var documentHeight=document.documentElement.offsetHeight;
var viewHeight=window.innerHeight;//getViewportHeight()

window.scrollTo(0,documentHeight-viewHeight);

这就设置了让浏览器滚动到特定位置,输入的是偏移量!

一般通过scrollLeft scrollTop来判断是否滚动了,以及滚动的距离是多少。

checkScrollSlide=function(parent,box){
    //兼容混杂和标准的 获取 滚动条的滚动距离
    var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
}

3.元素尺寸相关概念对比

offsetXXX VS clientXXX

  • offsetWidth offsetHeight以 CSS像素返回它的屏幕尺寸。返回的尺寸包括: 内容、边框border 和 内边距padding
  • clientWidth clientHeight 不包含边框大小,只包含:内容和padding(内边距)。 有滚动条的话,clientXXX也不包含滚动条.

getViewport 和 clinetWidth/Height
这个getViewport方法是在文档根元素查询这些属性,它的返回值和窗口的innerWidth innerHeight没有区别。

clientLeft clientTop

这个两个值一般返回的是 元素的 内边距的外边缘和边框外边缘(没有边框就是外边距内边缘)。 通常就等于left boder 和 top border

4 完整实现

我们获取知道了滚动距离后,还不够,我们要知道当前视口的大小,元素本身的尺寸,最后一个元素是哪个,以及该元素距离浏览器顶部的距离。

/*Example for scroll  implementation your detecting algorithm*/
function checkScroll(element,box,window){
    //最后一张图片距离顶部的距离+该元素一半的高度 lastBoxH
    var oBoxs=getByClass(element,box);//获取所有匹配这个样式名的子元素
    var lastBoxH=getElementPos(oBoxs[oBoxs.length-1]).y+Math.floor(oBoxs[oBoxs.length-1].offsetHeight/2);
    var view=getViewport(window);//view.width, view.height
    var scrollSize=getScrollOffsets(window);//scrollSize.x scroll.y
    return (lastBoxH<scrollSize.y+view.height);
}

原理: 获取当前视口大小,获取当前滚动条滚动的距离。如果视口的高度view.height加上滚动条滚动的垂直距离scrollSize.y 超过了当前最后一个元素的一般,就应该把整个元素渲染出来。

算法:比较 浏览器的滚动的距离+浏览器视口的高度 与 最后一张图片距离顶部的距离+该元素一半的高度(元素距离顶部距离+元素一半的高度。)

  1. 一种实现是checkScroll检测到了符合条件之后,才把这些元素一个一个渲染出来,如下:
    并且类名也是这时添加的。
var oBox=document.createElement('div');
oBox.className='box';
oParent.appendChild(oBox);
var oPic=document.createElement('div');
oPic.className='pic';
oBox.appendChild(oPic);
var oImg=document.createElement('img');
oImg.src=urlBase+count+".jpg";
oPic.appendChild(oImg);
  1. 另一种是先把所有图片都的HTML结构都渲染了,但是先不对src赋值,仅仅是渲染一个结构出来。 我们checkScroll 检测到 到符合条件,才加载图片(即添加src属性)。
    一般的话,这种要先把视口范围的图片先渲染出来了,然后才利用checkScroll来滚动加载

    前面的滚动检测仅仅是垂直方向上检测了,还有加上检测水平方向的以及元素底部也要检测。 也就是检测这个元素的矩形是否和可视区域的矩形重叠,重叠了就使它可视。

function checkScroll(element,box,window){
    //最后一张图片距离顶部的距离+该元素一半的高度 lastBoxH
    //var oBoxs=getByClass(element,box);//获取所有匹配这个样式名的子元素
    if(document.getElementsByClassName){
        var oBoxs=element.getElementsByClassName(box);
    }
    var ele=getElementPosSize(oBoxs[oBoxs.length-1]);
    var lastBoxH=ele.top+Math.floor(ele.height/2);
    var lastBoxW=ele.left+Math.floor(ele.width/2);
    var view=getViewport(window);//view.width, view.height
    var scrollSize=getScrollOffsets(window);//scrollSize.x scroll.y

     return (lastBoxH<scrollSize.top+view.height)&&(lastBoxW<view.width+scrollSize.left);
}

上面的检测方式,是对于有横向滚动条和垂直滚动条都适用的情况,不过这里比较的单位是一张图片的尺寸,距离和整个视口的比较。 一般来说,没有水平滚动条的时候,lastBoxW是元素距离最左边缘的距离加上本身的宽度的一半,这个值不可能比视口宽度大~
同理没有垂直滚动条的时候也成立。

有的解决方法是检测4个条件:(判断两个矩形是否相交)

//offsets.top滚动条距离  view.height视口高度 pos.top元素距离文档最上方的距离   pos.height元素高度
//元素从下方不可见,随着滚动条向上出现
var post=pos.top-(view.height+offsets.top);
//判断对象底部与文档顶部的距离, 是否大于滚动条距离,元素从上方不可见,向下进入可见。
var posb=pos.top+pos.height-offsets.top;

var posl=pos.left-(view.width+offsets.left);
var posr=pos.left+pos.width-offsets.left;
if((post<0&&posb>0)&&(posl<0&&posr>0)){
    ....
    设置图片url
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值