每天看一片代码系列(四):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方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
随机推荐
- x:Name与Name区别
x:Name与Name有两个不同点: 1.x:Name是Xaml的标记特性,任何在Xaml中定义的元素,都可以使用x:Name来为元素指定名称. Name是FrameworkElement定义的依赖项 ...
- ES6-模块导入导出
基本用法 命名导出(named exports) 可以直接在任何变量或者函数前面加上一个 export 关键字,就可以将它导出. 例如: export const sqrt = Math.sqrt; ...
- ctrl + alt + o 快速删除掉没有使用的 import
ctrl + alt + o 优化导入,可以快速删除掉没有使用的 import
- 用eclipse pydev 创建一个新py文件时 文件的coding设置问题
问题: 当安装好eclipse和pydev后,创建一个project, 创建一个新的py文件,文件头都会自带中文时间.这样在编译的时候会报错. 解决办法之一: 通过设置,可以使新建的文件的文件头自动带 ...
- CALayer & bitmap Content
Working with High-Resolution Images Layers do not have any inherent knowledge of the resolution of t ...
- UVa 11082 - Matrix Decompressing(最大流)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- 【[HNOI2015]菜肴制作】
\(SDSC\)讲过的题,复习一下 如果用一个小根堆来维护拓扑的话显然是会不行的,因为这样求出来的是字典序最小的拓扑序,并不一定是1尽可能在前 因为字典序是贪心的,如果前面的一位能小就尽可能的小,并不 ...
- MySQL数据库----------小知识点
**********************补2016年5月23日的博客************************* MySQL数据库 常用数据类型: int 整数 ...
- tp3.2中前台模板中日期时间的转换
{$vo.create_time|date='Y-m-d',###} 其中###是占位符
- [转]asp.net Request、Response 响应在此上下文中不可用
这个问题一般是在页面中使用了Respons.Write()方法,虽然是继承了System.Web.UI.Page.但System.Web.UI.Page下的Response只有在asp.net页面里才 ...