最近在做移动端的营销页面时,遇到了页面有大量图片的情况,于是很自然的想到了要使用图片lazyload,PC端用着jQuery,也有现成的插件。
但是在移动端,基本不用jQuery,于是就试着自己去造一下轮子。
实现lazyload并不难,我很快就想到以下几个步骤:

  1. 首先HTML中不直接写图片真实URL,而是用一个空图代替,如<img class="lazy" src="data:images/nopic.png" data-original="images/test.jpg">
  2. 监听滚动scroll事件
  3. 判断图片元素是否出现在屏幕中,如果是则替换src为data-original里的真实URL。

在这简单的几个步骤中,也有几个细节要点需要注意:

  1. 监听事件是scroll,需要考虑是否应用函数节流(毕竟移动端,性能问题不能忘)
  2. 在移动端,水平X方向的滚动是很方便的,判断图片是否出现时,需要考虑水平方向。
  3. 滚动一定距离再刷新页面时,页面会有一次滚动,空图占据的大小若比真实图片大,就会出现在这一次判断中本来不会出现的图,替换真实图片重排后,高度减小,顶上来了。空图如果比真实图片小,就会加载还不应该出现的图,lazyload的效果就打折扣了。PC可直接写定px值,移动端需要使用相似比例的空图。

其中上面要点2比较坑。

垂直Y方向直接监听window的scroll即可,但水平X方向的多半是页面内某个元素设定了一定区域并overflow:auto; 偏偏页面内元素的scroll事件是不会冒泡的,事件的bubbles为false,即不可冒泡

默认的页面滚动事件是可冒泡的,由document开始触发,冒泡到window,事件的bubbles为true,即可冒泡,最坑的是获取和设置scrollTop等值时,却是使用 body 或 html 元素,水平有限,不理解为什么会是割裂开的。

对于这个问题,暂时没想到好的解决方案,暂时用写2次的方法解决,如lazyload(window),再lazyload('#container')监听各自的事件

而判断图片是否出现时,刚开始我是使用elem.offsetTop对比scrollTop,后来发现offsetTop是相对最近的定位元素的,很容易就坑了。

一番寻觅后才发现 elem.getBoundingClientRect(),一番查资料后总结了这个方法的一些要点

elem.getBoundingClientRect() 获取 元素相对于浏览器窗口的距离,会受到滚动的影响,实时获取,translate,scale等transform属性也会影响结果
getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)。
该函数返回一个Object对象,该对象有6个属性:top,lef,right,bottom,width,height;
这里的top、left和css中的理解很相似,width、height是元素自身的宽高,
但是right,bottom和css中的理解有点不一样。right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。

踩完一些坑后,总算仿照PC端的jQuery插件完成了轮子,代码如下

function lazyload(options){
var settings = {
selector : 'img.lazy',
container : window,
threshold : 0,
failurelimit : 0,
dataAttribute : "data-original",
};
if(typeof options == 'object'){
for(var key in options){
settings[key] = options[key] || settings[key];
}
}
var tId = null;
var imgsArr = Array.prototype.slice.call(document.querySelectorAll(settings.selector));
function inViewport(elem, threshold){
var o = elem.getBoundingClientRect();
var pageWidth = document.documentElement.clientWidth;
var pageHeight = document.documentElement.clientHeight;
threshold = threshold || pageHeight/5;
return o.left < pageWidth + threshold && o.top < pageHeight + threshold
}
function loadImg(){
clearTimeout(tId);
tId = setTimeout(function(){
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var src = '';
var item = null;
var counter = 0;
if(imgsArr.length > 0){
for (var i = 0; i < imgsArr.length; i++) {
item = imgsArr[i];
if( inViewport(item) ){
src = item.getAttribute(settings.dataAttribute);
item.setAttribute('src', src);
imgsArr.splice(i,1);
i--;
counter = 0;
}else if( ++counter > settings.failurelimit ){
break;
}
};
}else {
settings.container.removeEventListener('scroll',loadImg);
}
}, 100);
}
loadImg();
settings.container.addEventListener('scroll',loadImg);
}

使用时和jQuery的lazyload插件类似,只是没有了$,直接使用函数lazyload();默认配置如下

lazyload({
selector : 'img.lazy', // 选择器
container : window, // 容器
threshold : 0, // 预留间距,即图片距离屏幕还有一定距离就预先加载
failurelimit : 0, // failurelimit,值为数字.lazyload默认在找到第一张不在可见区域里的图片时则不再继续加载,但当HTML容器混乱的时候可能出现可见区域内图片并没加载出来的情况,failurelimit意在加载N张可见区域外的图片,以避免出现这个问题.
dataAttribute : "data-original", // 存放真实URL的属性
});

以上实现还没有测试兼容,纯属交流,欢迎指正

移动端图片滚动加载-lazyload实现的要点总结的更多相关文章

  1. [js开源组件开发]图片懒加载lazyload

    图片懒加载lazyload 前端对请求的一种优化方式,为什么叫懒加载,无从查起,反正我当初一直认为它是滚动加载的一种类型.它主要是以图片或背景在可视区域内时才显示真正的图片,减少src带来的负荷.所以 ...

  2. js插件---图片懒加载lazyload

    js插件---图片懒加载lazyload 一.总结 一句话总结:使用异常简单,src里面放加载的图片,data-original里面放原图片,不懂的位置去官网或者github找API就好. 1.laz ...

  3. 图片懒加载--lazyload.js的用法

    这几天公司的项目已经完成的差不多了,只剩下各种优化问题.今天着重于图片加载的优化.当一个页面需要下拉很长而且又有过多的图片要加载时,就会发生很多http请求,就会拉慢网页加载速度,用户体验不友好.怎么 ...

  4. 前端性能优化--图片懒加载(lazyload image)

    话说前头: 上次写了一篇webpack的学习心得,webpack能做到提升前端的性能,其模块打包最终生成一个或少量的文件能够减少对服务端的请求.除此之外,本次的图片懒加载(当然不仅限于图片,还可以有视 ...

  5. 前端性能优化成神之路--图片懒加载(lazyload image)

    图片懒加载(当然不仅限于图片,还可以有视频,flash)也是一种优化前端性能的方式.使用懒加载可以想要看图片时才加载图片,而不是一次性加载所有的图片,从而在一定程度从减少服务端的请求 什么是懒加载 懒 ...

  6. 前端实现图片懒加载(lazyload)的两种方式

    在实际的项目开发中,我们通常会遇见这样的场景:一个页面有很多图片,而首屏出现的图片大概就一两张,那么我们还要一次性把所有图片都加载出来吗?显然这是愚蠢的,不仅影响页面渲染速度,还浪费带宽.这也就是们通 ...

  7. 插件:★★★ !!!图片懒加载 lazyload.js 、 jquery.scrollLoading.js

    插件:图片懒加载 jquery.lazyload.js 2016-3-31 插件说明:http://www.w3cways.com/1765.html (小插件,好用) 下载地址: https://r ...

  8. 图片懒加载lazyload.js详解

    简介 lazyload.js用于长页面图片的延迟加载,视口外的图片会在窗口滚动到它的位置时再进行加载,这是与预加载相反的. 优点 它可以提高页面加载速度: 在某些情况清晰它也可以帮助减少服务器负载. ...

  9. jQuery插件图片懒加载lazyload

    来自XXX的前言: 什么是ImageLazyLoad技术 在页面上图片比较多的时候,打开一张页面必然引起与服务器大数据量的 交互.尤其是对于高清晰的图片,占的几M的空间.ImageLazyLoad技术 ...

随机推荐

  1. IEE数据库安装向导

    RHEL 5用rpm包,直接安装后配置数据及缓存目录即可. RHEL 6用tar包+配置文件,本文是在RHEL 6上安装IEE的向导. ①上传infobright-4.0.6-x86_64.tar包和 ...

  2. 可视化工具gephi源码探秘(二)---导入netbeans

    在上篇<可视化工具gephi源码探秘(一)>中主要介绍了如何将gephi的源码导入myeclipse中遇到的一些问题,此篇接着上篇而来,主要讲解当下通过myeclipse导入gephi源码 ...

  3. Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列二十】

    <Web 前端开发精华文章推荐>2013年第八期(总第二十期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HTML5 和 C ...

  4. Cannot override the final method from SherlockFragmentActivity

    调用ActionBarSherlock后页面找不到onCreateOptionsMenu报错 com.actionbarsherlock.app.SherlockFragmentActivity.on ...

  5. html选中图片时,在页面回写图片

    我们经常会遇到这种情况,就是上传一个图片,但是点击一个图片的时候,最好是可以在浏览器预览这个图片,不然用户还以为没有选择图片呢,但是浏览器的安全机制却阻止了这个问题,就是当访问的是网络上的网站的时候, ...

  6. [SDK2.2]Windows Azure Cloud Service (35) 使用VS2013发布Azure Cloud Service

    <Windows Azure Platform 系列文章目录> 好久没有更新BLOG了,今天我们继续Windows Azure相关的内容. 笔者最近把Visual Studio升级到了20 ...

  7. Elasticsearch增删改查 之 —— Get查询

    GET API是Elasticsearch中常用的操作,一般用于验证文档是否存在:或者执行CURD中的文档查询.与检索不同的是,GET查询是实时查询,可以实时查询到索引结果.而检索则是需要经过处理,一 ...

  8. java继承的对象中构造函数的调用顺序

    建立两个继承关系的对象 public class Machine { public String machieNameString; public Machine() { System.out.pri ...

  9. 介绍开源的.net通信框架NetworkComms框架 源码分析(二十一 )TCPConnectionListener

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  10. jquery更改加载图片大小

    <script type="text/javascript"> $("img").css("width","80%&q ...