每天看一片代码系列(四):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方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
随机推荐
- Linux汉化(Cent Os汉化)
在腾讯云上购买了Cent Os7.1的云服务器,是英文版啊,有没有?对于我这种英文的渣渣啊,所以我要用中文版,我就是这么low,怎么着呢? Ok ,在汉化之前,先查看系统的语言环境, echo $LA ...
- c++内存区域结构及堆栈的一些知识
一.c++在内存区域的分配图 可以看出,对于Linux系统下的,存储空间的分配有着较为层次清晰的分层.单片机大概也遵循这个分区架构. 二进制代码以及常量(CONST修饰)以及全局变量在最底层,存储空间 ...
- reactnative调研
/** * This function parses the exported methods inside RCTBridgeModules and * generates an array ...
- mint-ui 填坑之路
swipe组件 因为项目加载eslint的缘故也就没有像之前的项目一样引用swiper框架.这个轮播图的组件文档实在是不敢恭维(尽管其他的文档也好不到哪里去),官方给出的参数真是少的可怜,一些方法也并 ...
- PAT——1011. A+B和C
给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组占一行,顺序给出A.B ...
- javaWeb中怎么获取提交表单里面的值
在javaWeb中如何获得html文件中的表单里面的值? <!DOCTYPE html> <html> <head> <meta charset=" ...
- 基于VC++的WinCE网口通信
基于VC++的WinCE网口通信 WinCE下的网络编程与Windows下的非常类似,只是个别API函数有所不同.同样分为UDP和TCP两种,UDP就是无连接的通信,通过“用户数据报协议”(UDP)来 ...
- 一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList
一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) S ...
- IOC-AutoFac
学习过程中参考博客: AutoFac文档:http://www.cnblogs.com/wolegequ/archive/2012/06/09/2543487.html AutoFac使用方法总结:P ...
- MyBatis之properties配置
这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递.例如: <properties resource=" ...