每天看一片代码系列(四):layzr.js,处理图片懒加载的库
所谓图片的懒加载,即只有当图片处于或者接近于当前视窗时才开始加载图片。该库的使用方法非常简单:
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);
}
}
}
总结
- 基本流程: 滚动--》记录位置--》遍历图片--》判断是否在视窗中--》从属性中获取并设置图像src--》调用回调函数
- window.scrollY || window.pageYOffset 用于获取垂直滚动的距离
- 视窗高度:window.innerHeight,元素高度: node.offsetHeight
- 获取元素相对于doucment顶部的距离:http://stackoverflow.com/questions/5598743/finding-elements-position-relative-to-the-document
每天看一片代码系列(四):layzr.js,处理图片懒加载的库的更多相关文章
- 使用Webpack的代码拆分在Vue中进行懒加载
参考学习:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/ 学习文案:https://webpac ...
- webpack4 系列教程(七): SCSS提取和懒加载
教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步>>> (原文)webpack4 系列教程(七): SCSS 提取和懒加载. 个人技术小站: https://god ...
- webpack4 系列教程(四): 单页面解决方案--代码分割和懒加载
本节课讲解webpack4打包单页应用过程中的代码分割和代码懒加载.不同于多页面应用的提取公共代码,单页面的代码分割和懒加载不是通过webpack配置来实现的,而是通过webpack的写法和内置函数实 ...
- 【Java EE 学习 47】【Hibernate学习第四天】【sesion】【一级缓存】【懒加载】
一.Session概述 1.Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法. 2.理解Sessi ...
- 代码: 两列图片瀑布流(一次后台取数据,图片懒加载。下拉后分批显示图片。图片高度未知,当图片onload后才显示容器)
代码: 两列图片瀑布流(一次后台取数据,无ajax,图片懒加载.下拉后分批显示图片.图片高度未知,当图片onload后才显示容器) [思路]: 图片瀑布流,网上代码有多种实现方式,也有各类插件.没找到 ...
- 【SpringBoot 基础系列】实现一个自定义配置加载器(应用篇)
[SpringBoot 基础系列]实现一个自定义配置加载器(应用篇) Spring 中提供了@Value注解,用来绑定配置,可以实现从配置文件中,读取对应的配置并赋值给成员变量:某些时候,我们的配置可 ...
- Spring5.0源码学习系列之浅谈懒加载机制原理
前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文挑一个比较重要的知识点Bean的懒加载进行学习 1.什么是懒加载? 懒加载(Lazy-ini ...
- Vue总结第五天:vue-router (使用模块化(创建Vue组件)机制编程)、router-link 标签的属性、路由代码跳转、懒加载、路由嵌套(子路由)、路由传递数据、导航守卫)
Vue总结第五天:vue-router ✿ 路由(器)目录: □ vue中路由作用 □ vue-router基本使用 □ vue-router嵌套路由 □ vue-router参数传递 □ ...
- [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例
懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
随机推荐
- 简单封装的ajax请求
简单封装了一个ajax请求,做一下统一处理,少写重复代码,只是一个初步的代码,没有经过优化. $.extend({ myAjax: function (option, rollBack) { var ...
- 利用Underscore求数组的交集、并集和差集
1 数组交集函数——intersection 数组的交集是指包含多个数组中的共同元素的一个数组,求数组的交集就是找出给定数组中的共有元素. 下面实现一个求两个数组交集的函数. 判断数组是够包含指定值, ...
- Spring Framework5.0 学习(4)—— 基本概念
1.0 控制反转(IOC)/依赖注入(DI) 通过依赖注入(DI),对象的依赖关系将由负责协调系统关系中各个对象的第三方组件在创建对象是设定.对象无需自行创建或管理它们的依赖关系——依赖关系将被自动 ...
- 关于Hibernate多对多关联关系的更新问题。
一个账套类Reckoning和账套项目类 AccountItem.这两个类是双向多对多关联关系. Reckoning.hbm.xml文件的配置如下 <set name="account ...
- import(导入)过期的磁带 -----先留个引子,后期更改补充
在某些情况下,客户需要恢复已经过期的磁带上的数据, 如果磁带没有被重新使用,数据没有被覆盖掉,可以使用 netbackup 的 import 方法将过期的磁带上的数据 import 到 netback ...
- 记一次关于SSM框架的使用错误
今天遇到一个十分操蛋的问题,最后发现是因为忘记在对应的Service上加上@AutoWired. 难怪单元测试没问题,因为单元测试中用到的Service,其实现类通过DAO自动装配了.也就是在对应的s ...
- JavaScript在浏览器中把文本保存为文件的方法
JavaScript在浏览器中把文本保存为文件的方法 经过测试第二种方法可以保存更多的文本不至于卡死 var saveTextAsFile1 = function (text, fileName, s ...
- Network Security Threats
Network Security Combination of low-cost powerful computing and high-performance networks is a two-e ...
- 微信小程序开发——进阶篇
由于项目的原因,最近的工作一直围绕着微信小程序.现在也算告一段落,是时候整理一下这段时间的收获了.我维护的小程序有两个,分别是官方小程序和一个游戏为主的小程序.两个都是用了wepy进行开发,就是这个: ...
- VS2017无法打开Razor视图文件
VS2017一直卡顿就在扩展和更新里把没用的插件关闭了.导致后来一直NETCORE的Razor视图文件打不开 查了资料才知道需要依赖 ASP.NET Core Razor Language Servi ...