瀑布流特点:

1.图片长短不一,但排列整齐有序

2.中心思想:

根据可视区的宽度clientWidth,确定瀑布流的列数,

寻找高度最低的一列,每次循环遍历时,下一张图片应先从最低列下端续上,

每循环一次,每计算一次列数的总高度

每张后续图片采用定位的方式摆放

 

开篇先说几句:

1.这个瀑布流效果列数不定,适用于pc端.(移动端瀑布流后期奉上)

2.参考了一篇网文,但是看到有网友评论称“使用position定位的瀑布流都不算合格”,

在我仿照着实现瀑布流功能后,发现这位网友的评论确有道理,

因为每当浏览器可视区域宽度(clientWidth)变化时,由于定位的原因,出现了图片错位现象,在刷新浏览器的情况下方可解决.

3.参考文章的作者思路巧妙,值得学习模仿,因此有了此文.(您即将看到的代码已经过极度简化)

4.木有封装,相信您一定能看懂

先看一下瀑布流的效果图:

解析JS如何实现瀑布流效果

有长有短,图片的排列按照列数先短后长的顺序进行.

代码如下:

html部分:

<body> 
<!-- 为了节约篇幅,我减去了部分class='box'的div元素,可以根据需要自行添加 -->
  <div id="container">
      
      <div class="box">
          
        <img src="assets/22.jpg">
          
      </div>

      <div class="box">
          
        <img src="one.jpeg">
          
      </div>

      <div class="box">
          
        <img src="assets/timg.jpeg">
          
      </div>

      <div class="box">
          
        <img src="assets/1.jpg">
          
      </div>

      <div class="box">
          
        <img src="assets/22.jpg">
          
      </div>
      <div class="box">
          
        <img src="assets/2.jpg">
          
      </div>

      <div class="box">
          
        <img src="assets/11.jpg">
          
      </div>
      
  </div>   

为了节约篇幅,我的小盒子<div class="box">元素减去了不少,

如果您练习时为了追求明显的效果,可以后续添加n多个这样的小盒子

CSS部分:

无论父盒子还是子盒子,他们的宽高全靠其下一层内容来撑

<style>
    *{
        margin: 0px;
        padding: 0px;
    }

    /*将主容器的布局方式设置为相对布局,
    注意:js部分会为container添加上宽度,
     以实现margin:0 auto的样式需求*/

    #container{
      position: relative;
      margin:0 auto;  
    }

    .box{
      padding: 5px;
      float: left;  
    }

    /*图片尺寸*/
    .box img{
      width: 250px;
      height: auto;   
    }
  </style>

注意:container元素最初没有设置宽度,JS部分会为其计算出宽度,实现居中效果

JS部分:

  <script>
      
    window.onload = function(){

      // 获取浏览器可视区域宽度
      var clientWidth = document.documentElement.clientWidth;
      // 获取小盒子的数组
      var sons = document.getElementsByClassName('box')

      // 总宽度/小盒子的宽度,得出当前可视区可以放入几列图片,即获取列数
      var num = Math.floor(clientWidth/sons[0].offsetWidth)

      // 获取父盒子
      var father =  document.getElementById('container')
      //计算出父盒子的宽度
      father.style.cssText = 'width:' + sons[0].offsetWidth*num + 'px;'
     

      var rowBoxHeight = [];// 创建一个存放每一行高度值的数组

      for(var i = 0 ;i<sons.length;i++){
        
        //如果图片数量小于列数

        if(i < num){
          //两种把所得项放入新数组的方法
         // rowBoxHeight.push(sons[i].offsetHeight)//方法1
          
          rowBoxHeight[i] = sons[i].offsetHeight // 方法2 新数组的每个值就是每个box的高度值

        } else {

          //如果图片数量大于列数,那么先找到每一列中最小高度
          // 注意Math.min.apply的用法
          var minHeight = Math.min.apply(null,rowBoxHeight)
          //找到最低高度的box的索引值
          for(let i in rowBoxHeight){

            if(rowBoxHeight[i] == minHeight){
              var minHeightIndex = i;
            }

          }
          
          // 即将续上的图片的布局方式是绝对布局
          sons[i].style.position = 'absolute';
          // top值为为最低高度box的高度
          sons[i].style.top = minHeight +'px';
          //left值最低高度box的坐标offsetLeft
          sons[i].style.left = sons[minHeightIndex].offsetLeft +'px';
          //新续上的图片改变了该数列的高度,所以,及时更新数列高度,为下一轮循环高度比较做准备
          rowBoxHeight[minHeightIndex] +=   sons[i].offsetHeight;

        }
       
      }
     

    }  
  
  </script>

注意点:

1.window.onload保证图片加载完成后,可以获取到正确的offsetHeight;

2.Math.min() 返回一组表达式中最小者,apply使得数组可以使用Math.min方法

Math.max()  返回一组表达式中的最大者

3.两种为数组添加成员的方式

rowBoxHeight.push(sons[i].offsetHeight)

rowBoxHeight[i] = sons[i].offsetHeight  

4.新续上的图片改变了该数列的高度,所以,及时更新数列高度,

为下一轮循环高度比较做准备.

列的高度 = 列的最低高度 + 新续的图片高度

rowBoxHeight[minHeightIndex] += sons[i].offsetHeight;

相关文章:

猜你喜欢
相关资源
相似解决方案