图片延迟加载库Layzr

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 创业者,程序员(Java,R,Javascript/Nodejs)
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-layzr/

js-layzr

前言

延迟加载技术,普遍应用于现在大部分的互联网的Web应用上。通过对图像的延迟加载,等到用户浏览区域接近时才把图片进行加载,可以有效地提升网页打开的速度,进一步改进用户的体验。

Layzr.js库就可以完成这个功能,150多行代码,很小很快很方便。

目录

  1. layzr介绍
  2. layzr的基本使用
  3. Layzr的配置

1. layzr介绍

layzr.js 是一个很小、速度快、无依赖的,用于浏览器图片延迟加载的库。

我们找到Layzr.js官方的Github上面,dist目录发布的 layzr.min.js 仅有 2.2 KB。同时,发现 package.json 文件,没有任何的dependencies依赖。

用layzr.js进行图片延迟加载,是非常方便的。通过配置选项,实现最大化的加载速度。layzr.js对于滚动事件已去抖,以尽量减少对浏览器的压力,以确保最佳的渲染。

项目官方网站:http://callmecavs.github.io/layzr.js/

2. layzr的基本使用

layzr.js是在浏览器端运行的Javascript库,但是他是用于NPM管理的,还在没有bower中发布。关于NPM和Bower的介绍,请分别查看文章:快速创建基于npm的nodejs库bower解决js的依赖管理

下面我们用npm的方式,下载layzr库。

首先,创建项目目录。


~  D:\workspace\javascript> mkdir js-layzr && cd js-layzr 

新建NPM项目文件package.json。


~ D:\workspace\javascript\js-layzr> vi package.json
{
    "name": "js-layzr",
    "version": "0.0.1",
    "description": "a demo for layzr",
    "dependencies": {}
}

通过NPM下载layzr.js包


~ D:\workspace\javascript\js-layzr> npm install layzr.js --save
npm WARN package.json js-layzr@0.0.1 No repository field.
npm WARN package.json js-layzr@0.0.1 No README data
layzr.js@1.1.4 node_modules\layzr.js

layzr1

接下来,我们打开layzr.js项目提供的Demo的文件,在layzr.js/demo.html。


<!DOCTYPE html>

<!--[if IE 9]>         <html class="ie9" lang="en-US"> <![endif]-->
<!--[if gt IE 9]><!--> <html lang="en-US"> <!--<![endif]-->
  <head>
    <title></title>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
      .demo-images {
        width: 300px;
        margin-right: auto;
        margin-left: auto;
        padding-top: 50vh;
      }

      .demo-image,
      iframe {
        display: block;
        margin-bottom: 100px;
      }
    </style>
  </head>
  <body>
    <div class="wrapper">

      <div class="demo-images">
        <img class="demo-image" src="http://placehold.it/300">
        <img class="demo-image" data-layzr="http://placehold.it/300">
        <img class="demo-image" data-layzr="http://placehold.it/300" data-layzr-retina="http://placehold.it/300&text=retina" data-layzr-bg>
        <img class="demo-image" data-layzr="http://placehold.it/300" data-layzr-retina="http://placehold.it/300&text=retina">
        <img class="demo-image" data-layzr="http://placehold.it/300" data-layzr-retina="http://placehold.it/300&text=retina">
        <img class="demo-image" data-layzr="http://placehold.it/300" data-layzr-retina="http://placehold.it/300&text=retina">
        <iframe width="300" height="169" data-layzr="https://www.youtube.com/embed/2a01Rg2g2Z8"></iframe>
      </div>

    </div><!-- END wrapper -->

    <script src="dist/layzr.js"></script>
    <script>
      // create new instance, defaults shown below
      var layzr = new Layzr({
        selector: '[data-layzr]',
        attr: 'data-layzr',
        retinaAttr: 'data-layzr-retina',
        bgAttr: 'data-layzr-bg',
        threshold: 0,
        callback: null
      });
    </script>
  </body>
</html>

在浏览型预览效果,如下图所示。

layzr2

左边为浏览器页面,右边为Chrome的开发者工具的Elements界面,红色直线为显示和代码的对应关系。当页面向下滚动时候,图片会一张一张的加载。同时代码中,原代码为


<img class="demo-image" data-layzr="http://placehold.it/300" data-layzr-retina="http://placehold.it/300&text=retina">

的部分,会被重新翻译为


<img class="demo-image" src="http://placehold.it/300">

从本Demo中,我们可以猜出layzr库应该有2个组成部分,监听页面事件 和 更新img标签的DOM元素。

3. Layzr的配置选择

在HTML中,图片是用img标签在控制的,要用到Layzr.js库,需要在img标签中增加属性。


<img src="optional/placeholder" data-layzr="normal/image" data-layzr-retina="optional/retina/image" data-layzr-bg >
  • src: 用于定义图像占位符,如果没有定义图像占位符,那么在图像载入前,可能会显示异常。
  • data-layzr: 用于显示的图像
  • data-layzr-retina: 用于图像的延迟加载,测试发现没效果。
  • data-layzr-bg: 图像用于做成背景,测试发现直接被隐藏了。

对应地,我们还需要定义Javascript的实例,用来启动layzr的事件。


var layzr = new Layzr({ 
  selector: '[data-layzr]', 
  attr: 'data-layzr', 
  retinaAttr: 'data-layzr-retina', 
  bgAttr: 'data-layzr-bg', 
  threshold: 0, 
  callback: null 
});

Javascript实例属性:

  • selector: 用于选定图像标签。
  • attr: 用于指定data-layzr的属性
  • retinaAttr: 用于指定data-layzr-retina属性
  • bgAttr: 用于指定data-layzr-bg的属性
  • threshold: 用于定义图像加载参数,通过屏幕高度来控制。
  • callback: 当加载完成,触发事件回调。

接下来,我们新建一个layzr.html的文件,用于测试 layzr 的库各种功能,会比官方提供的Demo更易于理解。

新建文件layzr.html。


<!DOCTYPE html>
<html>
<head>
    <title>Layzr Demo</title>
    <script src="node_modules/layzr.js/dist/layzr.js"></script>
    <style>
        .row {
            margin: 50px 0;
            height: 500px;
        }
        .border {
            padding: 10px;
            border-style: solid;
            border-width: 3px;
            border-color: blue;
        }
    </style>
</head>
<body>
<div class="wrapper">
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2015/02/marked.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2015/03/buffer.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2015/02/express4.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2015/03/child_process.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2015/03/crypto.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr="http://blog.fens.me/wp-content/uploads/2014/02/architect.png">
        </div>
        <div class="row">
            <img src="./bg.png" data-layzr-retina="./bg2.png" data-layzr="http://blog.fens.me/wp-content/uploads/2013/08/seo-title.png">
        </div>
</div>

<script>
    var layzr = new Layzr({
        selector: '[data-layzr]',
        attr: 'data-layzr',
        retinaAttr: 'data-layzr-retina',
        threshold: 10,
        callback: function () {
            console.log(this);
            this.classList.add('border');
        }
    });
</script>

</body>
</html>

用浏览器找开页面,我们可以看到展示效果。

layzr3

当浏览器向下滑动的过程中,图片由原来黑色的占位图,会自动替换为我们需要显示的图片。

layzr4

本文测试的代码,已上传到github:https://github.com/bsspirit/js-layzr

这样,我们就实现图像的延迟加载技术。对于有大量图片的网站来说,尝试一下图像的延迟加载技术,肯定会给网站带来大幅度的性能改进的。

转载请注明出处:
http://blog.fens.me/nodejs-layzr/

打赏作者

This entry was posted in Javascript语言实践

  • lee

    data-layzr-retina 貌似是在高分辨率下的设备下 显示更清楚的图片

    • 我测试过也看了源代码,没有什么特别的用处。我估计就是作者,原来设计这个属性后台决定用 src 代替了。

      https://github.com/bsspirit/js-layzr/blob/master/node_modules/layzr.js/dist/layzr.js 19行-29行

      • zkaip

        API文档写的是如果屏幕分辨率满足 retina 要求,则用 data-layzr-retina 的图片

        • retina 是不是针对 MAC的配置啊?

          • zkaip

            This source will only be loaded if the devicePixelRatio is greater than 1.

            //window.devicePixelRatio;

            MBP上的 window.devicePixelRatio 大于1
            所以可以使用 data-layzr-retina

          • OK,了解了。

  • lifetin

    requestAnimationFrame 和cancelAnimationFrame
    在有些浏览器不兼容,比喻一加手机.花了两个小时找出来的.要做下兼容

    var lastTime = 0;
    if ( !(‘requestAnimationFrame’ in window) || !(‘cancelAnimationFrame’ in window) ) {
    requestAnimationFrame = function( callback, element ) {
    var currTime = new Date().getTime();
    //为了使setTimteout的尽可能的接近每秒60帧的效果
    var timeToCall = Math.max( 0, 16 – ( currTime – lastTime ) );
    var id = window.setTimeout( function() {
    callback( currTime + timeToCall );
    }, timeToCall );
    lastTime = currTime + timeToCall;
    return id;
    };

    cancelAnimationFrame = function( id ) {
    window.clearTimeout( id );
    };
    }

    • 可以给这个包的提个补丁,确实缺少兼容性检查。