前端|浅析瀑布流布局及其原理

一、什么是瀑布流

很多时候我们会看到一些Vlog网站或者展示图片的网站,它们的图片明明每一张的高度大小都不同,但是却能自动地适应,排成一行一行地展示,并且下拉到底的时候,加载的图片也会自动适应,这就是瀑布流,比如下图。
前端|浅析瀑布流布局及其原理
文章图片

二、实现原理 要做到每一张图片都根据上面的高度自动适应排列,那么我们就不能单纯地靠html+css布局了,需要用到js来帮助计算位置(其实用CSS3也能布局)。那么计算什么呢?
首先,我们需要理清一个思路,就是这个布局是按一列列来看的,如下图:
前端|浅析瀑布流布局及其原理
文章图片

我们要做的,其实就是在每一列下面插入新的图片,这样它就会紧挨着上面的图片对齐。至于上面和下面的图片间距,那么很自然地是利用了margin和padding属性,不熟悉盒子属性的可以移步去理解padding和margin,等于理解了盒子模型这篇文章看看。
三、事先准备
  • 建议事前在网上随便下载15张以上的图片,不用理会长宽问题,这些都是可以用css设置的;
  • 准备好jQuery
  • 然后按照以下布局去把HTML结构和CSS样式写好:
Document 前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片
前端|浅析瀑布流布局及其原理
文章图片

css样式:
*{ margin: 0; padding: 0; border:none } body{ background: #ddd } .wrap{ width: auto; height: auto; position: relative; margin:0 auto; } .item{ float: left; width: 280px; height: auto; padding: 10px; margin: 10px; box-sizing: border-box; }.item img{ display: block; width:100%; border-radius: 10px; cursor: pointer; } .item img:hover{ background-color: gray; opacity: 0.5; }

至此,那么你的第一排就已经布局好了,接下来我们就是要用js去计算一页能有多少列图片以及如何在每一列里面插入新图片。
四、瀑布流的核心 【前端|浅析瀑布流布局及其原理】实现瀑布流的核心其实就两个:
  • 找出图片高度最小的那一列,再那一列插入,然后继续找下一个高度最小的,一直循环直到插满图片为止;
  • 计算出每一列距离浏览器整体的距离,也就是position里的leftright,有什么用呢?当你知道某一列的left的时候,相当于就知道了在它下面插入图片时,图片如何定位到这一列了,只要图片的left值和列是一样的,那么图片自然就插入到列里面了
实现代码如下:
var data=https://www.it610.com/article/[ {"src":"1.jpg"}, {"src":"2.jpg"}, {"src":"3.jpg"}, {"src":"4.jpg"}, {"src":"5.jpg"}, {"src":"6.jpg"}, {"src":"7.jpg"}, {"src":"8.jpg"}, {"src":"9.jpg"}, {"src":"10.jpg"}, {"src":"11.jpg"}, {"src":"12.jpg"}, {"src":"13.jpg"}, {"src":"14.jpg"}, {"src":"15.jpg"}, {"src":"16.jpg"}, {"src":"17.jpg"}, {"src":"18.jpg"}, ]$(function(){ var wrap=$('#wrap'); var boxes=wrap.children("div"); waterfall(wrap,boxes); $(this).scroll(function(event){ appendBox(wrap,boxes) }) }) // 主要瀑布流布局函数 function waterfall(wrap,boxes){ // 第一步:先获取能容纳的列数:窗口宽度/每列宽度 // +20是外边距 var boxswidth=boxes.eq(0).width()+40; var windowwidth=$(window).width(); var column=Math.floor(windowwidth/boxswidth); // 顺便计算得出容器的宽度,让盒子居中 var wrapwidth=column*boxswidth; wrap.width(wrapwidth) // 第二步:定义一个数组存储每一列的高度 var arr=new Array; // 遍历每一个盒子 for(var i=0; i=index){ return false; }; box.css({ 'position':'absolute', 'top':top, 'left':left, 'opacity':'0' }).stop().animate({/*第二行慢慢出来的动画*/ 'opacity':'1' },1000); getStartNumber=index; }; // 计算最小高度列的索引函数 function getMinIndex(minheight,arr){ var minindex=arr.indexOf(minheight) return minindex }// 判断是否在底部的函数 function getBottom(wrap){ // 获取最后一列的高度和滚动的高度+窗口高度的和,如果长的一列的高度比窗口+滚动的高度要小,说明到底了需要追加 var documentHeight=$(window).height(); var scrollHeight=$(window).scrollTop(); var boxes = wrap.children('div') var lastboxTop=boxes.eq(boxes.length-1).offset().top; var lastboxHeight=boxes.eq(boxes.length-1).height()+20; var totalHeight=lastboxHeight+lastboxTop return documentHeight+scrollHeight>=totalHeight?true:false; }// 追加瀑布流效果 function appendBox(wrap,boxes){ // 先判断是否展示到了底部 if(getBottom(wrap)){ for (i in data){ var addstr=" 前端|浅析瀑布流布局及其原理 " wrap.append(addstr) } }else{ return false } waterfall(wrap,wrap.children('div')) }

注意:这里面我还加入了瀑布流追加的效果,就是下拉到底会自动加载,不过图片是重复的,需要在js顶部先定义一组数据,用来替换生产里src,至于实现原理,不是本文重点,大家可以通过注释去尝试理解

    推荐阅读