美文网首页
懒加载和瀑布流布局

懒加载和瀑布流布局

作者: 饥人谷_阿银 | 来源:发表于2019-05-06 21:27 被阅读0次

    简述图片懒加载的实现原理

    原理:先将img标签中的src链接设为同一张图片(空白图片),将其真正的图片地址存储再img标签的自定义属性中(比如data-src)。当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果。

    这样做能防止页面一次性向服务器响应大量请求导致服务器响应慢,页面卡顿或崩溃等问题。

    简述瀑布流布局的实现原理

    瀑布流布局由pinterest.com网站首创,它的原理是:先通过计算出一排能够容纳几列元素,然后寻找各列之中所有元素高度之和的最小者,并将新的元素添加到该列上,然后继续寻找所有列的各元素之和的最小者,继续添加至该列上,如此循环下去,直至所有元素均能够按要求排列为止;

    简述木桶布局的实现原理(可选)

    参考

    高度一样,而宽度不同的布局方式称之为木桶布局。它有几个鲜明的特点: 每行的图片高度一致;每行的图片都是占满的。
    采用构造函数创建对象的方式来写这段代码,注意按照约定构造函数的首字母要大写。创建一个新对象,然后将构造函数的作用域赋给新对象,调用构造函数中的方法。

    函数名声明为 Barrel ,意为木桶。然后就要确定有哪些属性和方法。在理解了思路步骤的前提下,可以构思需要哪些属性、方法以及它们的作用。

    属性:

    每行图片的高度固定: rowHeight, 行高

    拥有一个固定的容器: DOM对象,一个容器 命名为 .ct。 还应该有行容器和图片容器,但是由于这两个容器内容数量不固定,所以在布局的时候再创建

    行容器的宽度: width, 获取ct的宽度

    存放每行图片的数组: imgArr[]。每次把加载的图片压入该数组,判断该行是否超出宽度。

    方法:

    拥有素材图片 : 通过getImgUrls()方法来获取图片链接,(或从数据库中获取图片)。这里是通过访问https://placeholder.com/ 网站来获取代码,具体后述
    加载图片信息: loadImg()方法来加载图片,以便获取图片信息,
    渲染图片队列: render() 改变图片的比例大小,计算一行可以放置多少个图片
    放置图片位置: layout() 将改变完大小的图片放置到页面上,append到对应的DOM元素节点上。具体关系对应前面的父子关系即可

    如何判断元素出现在用户视野?

    在用户的视野中有新的图片进入时才去判断


    image

    有两种情况:
    (一)获取窗口、窗口滚动和元素距离窗口顶部的偏移高度,计算元素是否出现在窗口可视范 围内;

           function isShow($el){
          var winH = $(window).height(),//获取窗口高度
                scrollH = $(window).scrollTop(),//获取窗口滚动高度
                top = $el.offset().top;//获取元素距离窗口顶部偏移高度
          if(top < scrollH + winH){
              return true;//在可视范围
            }else{
              return false;//不在可视范围
            }
          }
    

    (二)监听窗口滚动事件,检查元素是否在可视范围内;

        $(window).on('scroll', function(){//监听滚动事件
            checkShow();
        })
        checkShow();
        function checkShow(){//检查元素是否在可视范围内
            $('img').each(function(){//遍历每一个元素
                var $cur = $(this);
                if(!!isloaded($cur)){return;}//判断是否已加载
                if (isShow($cur)) {
                  setTimeout(function(){
                    showImg($cur);
                    },300)//设置时间是为了更好的看出效果
                };
            });
        }
    
    

    (三)元素显示的时候把之前的默认照片替换成data-src里的照片。

        function showImg($el){
            $el.attr('src', $el.attr('data-src'));
            $cur.data('isloaded',true);
        }
    
    

    如何判断浏览器滚动到最底部?

    和判断元素是否出现在用户视野中的做法是一样的

    /*页面的高度   $('body').height();
    用户滚动的距离 $(window).scrollTop()
    浏览器的高度 $(window).height()
    当浏览器的高度 + 用户滚动的距离  = 页面的高度  我们可以判断浏览器滚动到最低部了
    */
    
    if($(window).height() + $(window).scrollTop() = $('body').height()) {
          console.log('到达浏览器底部')
    }
    

    懒加载示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
    </head>
    <body>
        <div class="container">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="1" data-src="http://cdn.jirengu.com/book.jirengu.com/img/1.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="2" data-src="http://cdn.jirengu.com/book.jirengu.com/img/2.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="3" data-src="http://cdn.jirengu.com/book.jirengu.com/img/3.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="4" data-src="http://cdn.jirengu.com/book.jirengu.com/img/4.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="5" data-src="http://cdn.jirengu.com/book.jirengu.com/img/5.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="6" data-src="http://cdn.jirengu.com/book.jirengu.com/img/6.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="7" data-src="http://cdn.jirengu.com/book.jirengu.com/img/7.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="8" data-src="http://cdn.jirengu.com/book.jirengu.com/img/8.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="9" data-src="http://cdn.jirengu.com/book.jirengu.com/img/9.jpg">
            <h2>测试</h2>
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="10" data-src="http://cdn.jirengu.com/book.jirengu.com/img/10.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="11" data-src="http://cdn.jirengu.com/book.jirengu.com/img/11.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="12" data-src="http://cdn.jirengu.com/book.jirengu.com/img/12.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="13" data-src="http://cdn.jirengu.com/book.jirengu.com/img/13.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="14" data-src="http://cdn.jirengu.com/book.jirengu.com/img/14.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="15" data-src="http://cdn.jirengu.com/book.jirengu.com/img/15.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="16" data-src="http://cdn.jirengu.com/book.jirengu.com/img/16.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="17" data-src="http://cdn.jirengu.com/book.jirengu.com/img/17.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="18" data-src="http://cdn.jirengu.com/book.jirengu.com/img/18.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="19" data-src="http://cdn.jirengu.com/book.jirengu.com/img/19.jpg">
            <img src="http://smashinghub.com/wp-content/uploads/2014/08/cool-loading-animated-gif-3.gif" alt="20" data-src="http://cdn.jirengu.com/book.jirengu.com/img/20.jpg">        
        </div>
        <script>
    
        start()  //调用保证进入页面首页图片是可见的
        $(window).on('scroll',function() { 
           start() //页面滚动进行调用
        })// 页面滚动
    
        function start() {
            $('.container img').not('[data-isLoaded]').each(function() {//遍例img
                                //not 排除已经加载完成的图片
                var $node = $(this)
               if(isShow($node)) {
                    setTimeout(function() {
                        loadImg($node)
                    }, 500)
               }
           })
        }
    
        function isShow($node) {
            return $node.offset().top <= $(window).height() + $(window).scrollTop()
        }  //判断图片位置
    
        function loadImg($img) {
            $img.attr('src',$img.attr('data-src'))
            $img.attr('data-isLoaded',1) //对已经加载出来的图片添加属性
        }//进行图片加载
        </script>
    </body>
    </html>
    

    瀑布流布局

    瀑布流的效果:

    image

    瀑布流的排序:

      1. 每张图片的宽度是一致的
      1. 从左往右进行排序,第一排放不下则从第二排从新开始排列
      1. 第二排或者往后的每排图片放置的位置为上一排高度最小图片的下面依次排放

    瀑布流实现的原理

    1. 图片的位置摆放
    • 图片位置的摆放大致可以不添加样式一次放置
    • 通过设置成块级元素,进行摆放
    • 通过绝对定位来进行摆放
    1. 瀑布流图片/div容器的实现是通过对其进行绝对定位来实现的
    1. 假设X轴列有4张图片,宽度为100px; 那第一张left 值为0,第二张left值为100px,第三张为200px,第四张为300px;
    1. 图片的高度,我们需要通过对其图片的高度进行判断,让第二横对的图片首先放到 X 列高度最小的图片下面(如图所示,一横列为4张图片,第五张图片放在第二横列中,寻找到第二列的图片高度最低,就将图片当道第二列中。第6张图片寻找到第四列的高度低就将图片放到第四列中,下面每次都是这样)


      image

      3.因为图片的高度很重要,我们需要保存并进行比较,所以我们要用一个数组来接受图片的高度

    下面我们看一下简单的示例:
    HTML:

    <body>
        <div class="waterfall">
            <img src="http://via.placeholder.com/100x100" alt="300*40">
            <img src="http://via.placeholder.com/100x80" alt="300*100">
            <img src="http://via.placeholder.com/100x150" alt="300*100">
            <img src="http://via.placeholder.com/100x140" alt="300*100">
            <img src="http://via.placeholder.com/100x120" alt="300*100">
            <img src="http://via.placeholder.com/100x110" alt="300*100">
            <img src="http://via.placeholder.com/100x160" alt="300*100">
            <img src="http://via.placeholder.com/100x30" alt="300*100">
            <img src="http://via.placeholder.com/100x50" alt="300*100">
            <img src="http://via.placeholder.com/100x90" alt="300*100">
            <img src="http://via.placeholder.com/100x20" alt="300*100">
            <img src="http://via.placeholder.com/100x60" alt="300*100">
            <img src="http://via.placeholder.com/100x120" alt="300*100">
            <img src="http://via.placeholder.com/100x150" alt="300*100">
            <img src="http://via.placeholder.com/100x180" alt="300*100">
            <img src="http://via.placeholder.com/100x200" alt="300*100">
            <img src="http://via.placeholder.com/100x125" alt="300*100">
            <img src="http://via.placeholder.com/100x70" alt="300*100">
            <img src="http://via.placeholder.com/100x120" alt="300*100">
            <img src="http://via.placeholder.com/100x40" alt="300*100">
            <img src="http://via.placeholder.com/100x20" alt="300*100">
            <img src="http://via.placeholder.com/100x10" alt="300*100">
            <img src="http://via.placeholder.com/100x140" alt="300*100">
    
        </div>
        <script>
    
    

    CSS

    .waterfall {
            max-width: 600px;
            margin: 0 auto;
            position: relative;
        }
        .waterfall img {
            width: 100px;
            margin: 10px;
            position: absolute;
            transition: all .4s;
        }
    
    

    JS

    <script>
    var colCount   // 列数
        var colHeightArray = []  //列高度的空数组
        var imgWidth = $('.waterfall img').outerWidth(true)
                                        //outerWidth(true) 表示元素所占用的全部的大小 左右边距等
        colCount = Math.floor($('.waterfall').width()/imgWidth)
        console.log(colCount)
        for(var i=0;i<colCount;i++) {
            colHeightArray[i] = 0
        } // 数组初始化为0 
        $('.waterfall img').on('load',function() {
                var minValue = colHeightArray[0]
                var minIndex = 0
                for(var i=0;i<colCount;i++) {
                    if(colHeightArray[i]<minValue) {
                        minValue = colHeightArray[i]
                        minIndex = i
                    }
                }
                $(this).css({
                    left: minIndex * imgWidth,
                    top: minValue
                })
            colHeightArray[minIndex]+=$(this).outerHeight(true)    
        })
    
        $(window).on('resize',function() {
            //jQuery 事件 - resize() 方法 
            //对浏览器窗口调整大小进行计数
            colHeightArray = []
            colCount = Math.floor($('.waterfall').width()/imgWidth)
            for(var i=0;i<colCount;i++) {
                colHeightArray[i] = 0
            } // 数组初始化为0 
            $('.waterfall img').each(function() {
                var minValue = colHeightArray[0]
                var minIndex = 0
                for(var i=0;i<colCount;i++) {
                    if(colHeightArray[i]<minValue) {
                        minValue = colHeightArray[i]
                        minIndex = i
                    }
                }
                $(this).css({
                    left: minIndex * imgWidth,
                    top: minValue
                })
                colHeightArray[minIndex]+=$(this).outerHeight(true) 
            })
        })
        </script>
    
    

    效果展示:
    点击查看效果

    解析:

    var colCount   // 列数  
    var colHeightArray = []  //列高度的空数组
    colCount = Math.floor(($('.waterfall').width()/$('.waterfall img').outerWidth(true)))
    //outerWidth outerWidth() 方法返回第一个匹配元素的外部宽度。该方法包含 padding 和 border。提示:如需包含 margin,请使用 outerWidth(true)
    //通过```.waterfall```div的宽度除于图片的宽度,来获取列数
    console.log(colCount)  // 在控制台输出一下列数
    for(var i=0;i<colCount;i++) {
            colHeightArray[i] = 0  // 数组初始化为0 
    } 
    //通过循环来初始化我们用于存储每列高度的数组
    // 如果有4列,那么数组的值为  [0,0,0,0]
     $('.waterfall img').on('load',function() {
    //当图片加载完成后我们在对其进行排序
                var minValue = colHeightArray[0] // 设一个变量来接收图片的高度
                var minIndex = 0  // 设置变量来接收图片的下标
                for(var i=0;i<colCount;i++) {
                    if(colHeightArray[i]<minValue) {  //
                        minValue = colHeightArray[i]
                        minIndex = i
                    }
                //通过if判断来对数组里面的高度进行排序,minIndex数组的下标把最小的图片放到相应的位置上
                }
    console.log(colHeightArray)//可以清楚的看到数组的变化,if判断不断数组中的最小值
    
                // 对图片进行摆放
                $(this).css({
                    left: minIndex * imgWidth, // 图片的left为数组的下标乘于图片的宽度
                    top: minValue // 高度就是最小值图片的高度
                })
            colHeightArray[minIndex]+=$(this).outerHeight(true)  //  数组中最小值等于当前最小值图片的高度  
        })
    

    相关文章

      网友评论

          本文标题:懒加载和瀑布流布局

          本文链接:https://www.haomeiwen.com/subject/xydjoqtx.html