所谓图片的懒加载,即只有当图片处于或者接近于当前视窗时才开始加载图片。该库的使用方法非常简单:

var layzr = new Layzr({
attr: 'data-layzr', // attr和retinaAttr必须至少有一个,用于指定对应的图片
retinaAttr: 'data-layzr-retina', // 一般对应的图像比attr要高清
threshold: 0, // 距离视窗的距离为多少时开始加载
callback: null // 回调函数
});

代码解析

首先是包装成为umd的方式:

(function(root, factory) {
if(typeof define === 'function' && define.amd) {
define([], factory); // 使用amd定义一个模块,依赖为空
} else if(typeof exports === 'object') {
module.exports = factory(); // cmd方式,暴露返回值
} else {
root.Layzr = factory(); // 浏览器环境下
}
}(this, function() { })

接下来是构造函数:

  function Layzr( options ) {
this._lastScroll = 0;
this._ticking = false; // 参数
this._optionsAttr = options.attr || 'data-layzr';
this._optionsAttrRetina = options.retinaAttr || 'data-layzr-retina';
this._optionsThreshold = options.threshold || 0;
this._optionsCallback = options.callback || null; // 获取合适的属性
this._retina = window.devicePixelRatio > 1;
this._imgAttr = this._retina ? this._optionsAttrRetina : this._optionsAttr; // 所有的图像集合
this._images = document.getElementsByTagName('img'); // call to create
this._create();
}

create和destory函数:

Layzr.prototype._create = function() {
// 记录初始的scroll位置
this._requestScroll(); // scroll和resize对应的事件处理函数
window.addEventListener('scroll', this._requestScroll.bind(this), false);
window.addEventListener('resize', this._requestScroll.bind(this), false);
} Layzr.prototype._destroy = function() {
// unbind事件
window.removeEventListener('scroll', this._requestScroll.bind(this), false);
window.removeEventListener('resize', this._requestScroll.bind(this), false);
}

requestScroll的具体实现:

  Layzr.prototype._requestScroll = function() {
this._lastScroll = window.scrollY || window.pageYOffset; // 垂直方向上的滚动距离
this._requestTick();
} Layzr.prototype._requestTick = function() {
if(!this._ticking) {
// requestAnimationFrame主要用于绘制图像,通过优化提高效率
// 这里用于每次滚动都调用update
requestAnimationFrame(this.update.bind(this));
this._ticking = true;
}
} Layzr.prototype.update = function() {
var imagesLength = this._images.length;
for(var i = 0; i < imagesLength; i++) {
var image = this._images[i]; // 如果当前的图片有设定的属性
if(image.hasAttribute(this._imgAttr) || image.hasAttribute(this._optionsAttr)) {
// 且已经处于视窗中
if(this._inViewport(image)) {
// 加载这个图片
this.reveal(image);
}
}
} // allow for more animation frames
this._ticking = false;
}

是否在视窗中的判断:

  Layzr.prototype._inViewport = function( imageNode ) {
// 视窗的顶部和底部
var viewportTop = this._lastScroll;
var viewportBottom = viewportTop + window.innerHeight; // 图像的顶部和底部
var elementTop = this._getOffset(imageNode);
var elementBottom = elementTop + imageNode.offsetHeight; // 计算threshold对应的像素
var threshold = (this._optionsThreshold / 100) * window.innerHeight; // 是否在这个区间中
return elementBottom >= viewportTop - threshold && elementBottom <= viewportBottom + threshold;
}

展示图像的实现:

Layzr.prototype.reveal = function( imageNode ) {
// 获取图像的src
var source = imageNode.getAttribute(this._imgAttr) || imageNode.getAttribute(this._optionsAttr); // 去除设置的属性
imageNode.removeAttribute(this._optionsAttr);
imageNode.removeAttribute(this._optionsAttrRetina); //设置src
if(source) {
imageNode.setAttribute('src', source); // 调用callback
if(typeof this._optionsCallback === 'function') {
this._optionsCallback.call(imageNode);
}
}
}

总结

  1. 基本流程: 滚动--》记录位置--》遍历图片--》判断是否在视窗中--》从属性中获取并设置图像src--》调用回调函数
  2. window.scrollY || window.pageYOffset 用于获取垂直滚动的距离
  3. 视窗高度:window.innerHeight,元素高度: node.offsetHeight
  4. 获取元素相对于doucment顶部的距离:http://stackoverflow.com/questions/5598743/finding-elements-position-relative-to-the-document

每天看一片代码系列(四):layzr.js,处理图片懒加载的库的更多相关文章

  1. 使用Webpack的代码拆分在Vue中进行懒加载

    参考学习:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/ 学习文案:https://webpac ...

  2. webpack4 系列教程(七): SCSS提取和懒加载

    教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步>>> (原文)webpack4 系列教程(七): SCSS 提取和懒加载. 个人技术小站: https://god ...

  3. webpack4 系列教程(四): 单页面解决方案--代码分割和懒加载

    本节课讲解webpack4打包单页应用过程中的代码分割和代码懒加载.不同于多页面应用的提取公共代码,单页面的代码分割和懒加载不是通过webpack配置来实现的,而是通过webpack的写法和内置函数实 ...

  4. 【Java EE 学习 47】【Hibernate学习第四天】【sesion】【一级缓存】【懒加载】

    一.Session概述 1.Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法. 2.理解Sessi ...

  5. 代码: 两列图片瀑布流(一次后台取数据,图片懒加载。下拉后分批显示图片。图片高度未知,当图片onload后才显示容器)

    代码: 两列图片瀑布流(一次后台取数据,无ajax,图片懒加载.下拉后分批显示图片.图片高度未知,当图片onload后才显示容器) [思路]: 图片瀑布流,网上代码有多种实现方式,也有各类插件.没找到 ...

  6. 【SpringBoot 基础系列】实现一个自定义配置加载器(应用篇)

    [SpringBoot 基础系列]实现一个自定义配置加载器(应用篇) Spring 中提供了@Value注解,用来绑定配置,可以实现从配置文件中,读取对应的配置并赋值给成员变量:某些时候,我们的配置可 ...

  7. Spring5.0源码学习系列之浅谈懒加载机制原理

    前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文挑一个比较重要的知识点Bean的懒加载进行学习 1.什么是懒加载? 懒加载(Lazy-ini ...

  8. Vue总结第五天:vue-router (使用模块化(创建Vue组件)机制编程)、router-link 标签的属性、路由代码跳转、懒加载、路由嵌套(子路由)、路由传递数据、导航守卫)

    Vue总结第五天:vue-router ✿ 路由(器)目录: □  vue中路由作用 □  vue-router基本使用 □  vue-router嵌套路由 □  vue-router参数传递 □  ...

  9. [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例

    懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...

随机推荐

  1. Linux汉化(Cent Os汉化)

    在腾讯云上购买了Cent Os7.1的云服务器,是英文版啊,有没有?对于我这种英文的渣渣啊,所以我要用中文版,我就是这么low,怎么着呢? Ok ,在汉化之前,先查看系统的语言环境, echo $LA ...

  2. c++内存区域结构及堆栈的一些知识

    一.c++在内存区域的分配图 可以看出,对于Linux系统下的,存储空间的分配有着较为层次清晰的分层.单片机大概也遵循这个分区架构. 二进制代码以及常量(CONST修饰)以及全局变量在最底层,存储空间 ...

  3. reactnative调研

    /**   * This function parses the exported methods inside RCTBridgeModules and   * generates an array ...

  4. mint-ui 填坑之路

    swipe组件 因为项目加载eslint的缘故也就没有像之前的项目一样引用swiper框架.这个轮播图的组件文档实在是不敢恭维(尽管其他的文档也好不到哪里去),官方给出的参数真是少的可怜,一些方法也并 ...

  5. PAT——1011. A+B和C

    给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组占一行,顺序给出A.B ...

  6. javaWeb中怎么获取提交表单里面的值

    在javaWeb中如何获得html文件中的表单里面的值? <!DOCTYPE html> <html> <head> <meta charset=" ...

  7. 基于VC++的WinCE网口通信

    基于VC++的WinCE网口通信 WinCE下的网络编程与Windows下的非常类似,只是个别API函数有所不同.同样分为UDP和TCP两种,UDP就是无连接的通信,通过“用户数据报协议”(UDP)来 ...

  8. 一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList

    一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) S ...

  9. IOC-AutoFac

    学习过程中参考博客: AutoFac文档:http://www.cnblogs.com/wolegequ/archive/2012/06/09/2543487.html AutoFac使用方法总结:P ...

  10. MyBatis之properties配置

    这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递.例如: <properties resource=" ...