懒加载和瀑布流布局

2019-05-06  本文已影响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. 瀑布流图片/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)  //  数组中最小值等于当前最小值图片的高度  
    })
上一篇下一篇

猜你喜欢

热点阅读