zoukankan      html  css  js  c++  java
  • 图片懒加载原理及实现

          由于过多的图片会严重影响网页的加载速度,并且移动网络下的流量消耗巨大,所以说延迟加载几乎是标配了。 

          图片懒加载的原理很简单,就是我们先设置图片的data-set属性(当然也可以是其他任意的,只要不会发送http请求就行了,作用就是为了存取值)值为其图片路径,由于不是src,所以不会发送http请求。 然后我们计算出页面scrollTop的高度和浏览器的高度之和, 如果图片举例页面顶端的坐标Y(相对于整个页面,而不是浏览器窗口)小于前两者之和,就说明图片就要显示出来了(合适的时机,当然也可以是其他情况),这时候我们再将 data-set 属性替换为 src 属性即可。

      

    图片延迟加载的使用场景?

       往往对于首页来说,图片较多者(并且固定了宽高、这样可以防止页面抖动、比如微博做的就非常不好,页面变化的厉害,得完!),我们都需要进行图片延迟加载的设定。   

       

    固定宽高的延迟加载

      这个实现起来比较简单,设置好固定宽高,那么使用上面所说的最简单的延迟加载即可。淘宝就是这么做的,当滚动到视窗可见的区域,就开始加载图片,否则不加载图片。

      

    非固定宽高的延迟加载

      第一种方法是: 使用padding-top或者padding-bottom来实现固定宽高比。 

      http://ju.outofmemory.cn/entry/22712

      这种方法的优点是纯css方案,缺点是html冗余,对输出到第三方不友好。

    <div style="padding-top:75%">
        <img data-src="" alt="" class="lazyload">
    <div>

      第二种方案是在页面初始化阶段利用ratio设置实际宽高值,优点是html干净,对输出到第三方友好,缺点是依赖js,理论上至少会抖动一次。

    <img data-src="" alt="" class="lazyload" data-ratio="0.75">

    进一步结合 srcset

    除了上面说的延迟加载,我们可以更进一步的引入srcset,通过设置srcset来保证加载最匹配的图片,这样对于一倍屏,二倍屏,三倍屏来说,可以做到不浪费流量且效果最好。

      

    延迟加载的开源解决方案

    jquery_lazyload

      这里有6489个star,说明还是很受欢迎的,但是它必须要依赖于jquery。 

    <img class="lazy" data-original="img/example.jpg" width="640" height="480">
    // 初始化
    $("img.lazy").lazyload();

    lazysizes 

      这个开源的库也有6406个star,好处在于他是原生js实现,不依赖于jquery/zepto, 自动监测可能发生变化的 lazyload 节点,不需要额外初始化, 并且支持响应式图片 srcset, 性能高,改善seo。强烈推荐!!!

      

    // 引入js文件
    <script src="lazysizes.min.js" async=""></script>
    
    // 非响应式 例子
    <img data-src="image.jpg" class="lazyload" />
    // 响应式 例子,自动计算合适的图片
    <img
        data-sizes="auto"
        data-src="image2.jpg"
        data-srcset="image1.jpg 300w,
        image2.jpg 600w,
        image3.jpg 900w" class="lazyload" />
    // iframe 例子
    <iframe frameborder="0"
        class="lazyload"
        allowfullscreen=""
        data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
    </iframe>

    lazyload

      需要基于jquery和zepto, 只有400多个star。 

    <!-- 直接赋予图片宽高 -->
    <img class="lazy" data-original="img/example.jpg" width="640" height="480">
    <!-- 或:通过css赋予图片宽高 -->
    <style>
        .lazy{640px;height:480px;}
    </style>
    <img class="lazy" data-original="img/example.jpg">
    <!-- 或:自适应宽度的图片样式(常用于移动端) -->
    <style>
        .lazy{100%;height:0;padding-top:75%;background-size:100%;}
        /* 假设高宽比为 480:640,即75%,并使用背景图的方式将图片铺在padding-top区域内
        (padding的百分比是宽度的百分比而不是高度的,即使是padding-top|padding-bottom) */
    </style>
    <div class="lazy" data-original="img/example.jpg"><div>
    <!-- 请参阅examples/enabled_image_full_width.html -->
    <!-- 初始化 -->
    $(".lazy").lazyload();

    vue-lazyload

      对于vue的项目使用vue-lazyload是再好不过的了,使用起来非常简单。

      首先npm install vue-lazyload --save, 接着引入到main.js:

    import VueLazyload from 'vue-lazyload'
    Vue.use(VueLazyload, {
      preLoad: 1.3,
      loading: 'http://cdn.uehtml.com/201402/1392662591495_1140x0.gif',
      error: 'https://cdn.dribbble.com/users/195330/screenshots/1545094/attachments/235536/21_404-error.png'
    });

       其中的preLoad选项是指在屏幕的多少倍的范围内开始加载,比如我们如果选择1.0那么几乎就是刚好在屏幕最下方的图片再向上拉时开始加载, 如果是0.5那么可能这个页面只有一半被加载了。 

      然后就可以在.vue文件中使用了:

    <img id="errorImg" v-lazy="'http://bbg-seller.oss-cn-qingdao.aliyuncs.com/test/gp/p1/' + item.picture" error="this.src=null;" >

      这样最基础的功能就实现了,是不是很简单呢?!

      

    微信如何实现延迟加载?

       研究了微信延迟加载的代码,还解决了一个问题,那就是常见于移动端的自适应宽度的延迟加载,即根据情况具体计算宽高。

    // 源码
    <img 
        data-s="300,640" 
        data-type="jpeg" 
        data-src="http://mmbiz.qpic.cn/mmbiz/meG6Vo0MeviaLibiaARRszfMpiaXtejcktPB2fK6uP13R4RS9Y7fHtk5bUd7A9R9zRyZ1nupW8ZVjHwBiaZUa3SkcPg/0?wx_fmt=jpeg" 
        data-ratio="0.8003597122302158" 
        data-w=""  
    />
    
    // 解析后的代码
    <img 
        data-s="300,640" 
        data-type="jpeg" 
        data-src="http://mmbiz.qpic.cn/mmbiz/meG6Vo0MeviaLibiaARRszfMpiaXtejcktPBLbT37dSYzNyhwDTiac0WiaribF0Vt7I3Zd7AG9xXSCUoch61KicnYnfqIw/0?wx_fmt=jpeg" 
        data-ratio="0.8003597122302158" 
        data-w="" 
        src="http://mmbiz.qpic.cn/mmbiz/meG6Vo0MeviaLibiaARRszfMpiaXtejcktPBLbT37dSYzNyhwDTiac0WiaribF0Vt7I3Zd7AG9xXSCUoch61KicnYnfqIw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&retryload=1" 
        style=" 414px !important; visibility: visible !important; height: 331.349px !important;" 
    />
    
    /* 其中
    data-s:表示可选的图片尺寸大小
    data-type:表示图片类型
    data-src:表示图片链接
    data-ratio:表示长宽比
    */

    由于源码是压缩模式的,做简单的猜测如下:

    1. 对于延迟加载,微信采用的模式和正常的延迟加载的模式类似,即用data-src存储真实的图片链接
    2. 为了解决移动端的自适应宽度的问题,微信存储了长宽比,然后进入页面就计算在不同设备里的真实宽高,并设置在style

    1.接入第三方平台的网页怎么处理?
    由于好奇心日报的文章会输出到第三方平台,比如今日头条/一点资讯等平台,这些平台对html都有一定的规范。这时候就需要后台在输出之前对html做一些转换。
    为了简单起见,类似<div class="lazy" data-original="img/example.jpg"><div>的方案不太适合让后台转换,所以微信这种动态计算方法可以借鉴。

    2.怎么处理响应式图片?
    响应式图片能够根据当前屏幕分辨率加载最匹配的图片,能够因地制宜,详见图片响应式解决方案

    3. 方案有了,回头追加一篇具体实践踩坑的博文

      

      

       

       

      

  • 相关阅读:
    SpringBoot基础
    开始一个新的springboot项目checklist
    五项修炼: 终生学习者
    价值流分析-改进方法论
    伯努利方程
    会计语言
    svg蒙版mask
    从svg到计算机图形学
    xflux 调节屏幕色温
    处理器架构
  • 原文地址:https://www.cnblogs.com/zhuzhenwei918/p/6943156.html
Copyright © 2011-2022 走看看