是开头都会说的原理
瀑布流布局有两种,一种是固定列,一种是非固定列。在此主要记述第一种的实现。
固定列的特征是:无论页面如何缩放,每行的总列数都一致。
一行4列的瀑布流从布局的角度来说,就是4个li标签。通过一定的事件(比如滚动条滚动多少px),然后读取之,再把数据动态地添加到页面中。
添加数据原则,不是根据li索引值来加,而是根据各列中高度最短的的那列动态添加。否则可能导致页面很难看(左右高度不统一)。
实例涉及ajax方法。可在服务器环境下运行。
废话不多说了。直接上样式。
<ul> <li> <div> <img src="https://www.jb51.net/images/1.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="https://www.jb51.net/images/2.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="https://www.jb51.net/images/3.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="https://www.jb51.net/images/4.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> </ul>
css
*{ margin:0; padding: 0; } ul li{ list-style: none; } #ul1{ width: 1080px; margin: 100px auto 0; } li{ width: 247px; float: left; margin-right: 10px; } li div{ border:1px solid #000;padding:10px; margin-bottom:10px; } li div img{ width: 225px;display: block; }
基本效果如图:
样式显示没问题之后,就把li里面的代码删掉。
接下来通过ajax来动态添加。
数据哪里来?
这里用的是wookmark的数据接口。
点开url得到是一个json。
信息量很大。怎么分析?
一般可以看文档。但是手头没有文档的情况下,可以看看链接。返回是什么鬼。
function createUrl(num){ return 'http://www.wookmark.com/api/json/popular?page='+num+'&callback=?'; } $(function(){ $.getJSON(createUrl(1),function(data){ console.log(data); }) })
控制台打印结果为:
原来是一个50个图片信息组成的数组。每个数组元素都是一个json。在这个简单的demo里面,暂时只需要取preview属性和title属性就好了。
布局实现
关键之一在于,判断最短的li,事实上我们需要最短高度li的索引值。
//找出高度最小li的索引值 function getShortestLi(){ var shortest=0; for(var i=1;i<4;i++){ if($('li').eq(i).height()<$('li').eq(shortest).height()){ shortest=i; } } return shortest; }
然后就是getJSON方法
$(function(){ $.getJSON(createUrl(1),function(data){ //console.log(data); for(var i=0;i<dataArr.length;i++){ var $html=$('<div><img src="'https://www.jb51.net/+data[i].preview+'"><p>'+data[i].title+'</p></div>'); //console.log($('li').eq(getShortestLi()).height()) $('li').eq(getShortestLi()).append($html); }; console.log([$('li').eq(0).height(),$('li').eq(1).height(),$('li').eq(2).height(),$('li').eq(3).height()]) }) })
再加载看看,布局就出来了。简单又漂亮。
做到这里,看起来一切都挺好。然而潜伏着一个致命的问题。
for循环惹的祸?
看看console.log的信息。为了分析,我把4个li的高度放进了一个数组:
50张图片分4列,少说平均高度也得有三四千像素。
而到循环结束,程序判断的终点竟然只有令人发指的1000多个px,因为图片加载过程慢于for循环执行速度。虽然demo里的显示还算正常,但这种代码在网速不好时,会造成工作事故。
思路一:可以判断图片是否加载完成。
可以用个定时器监听下,然后用递归实现,我的方案是这样
var index=0; function LoadPic(index){ var $html=$('<div><img src="'https://www.jb51.net/+data[index].preview+'"><p>'+data[index].title+'</p></div>') $('li').eq(getShortestLi()).append($html); var oImg=$html.find('img'); var t=setInterval(function(){ if(oImg.height()!=0){//如果加载完了。 clearInterval(t); //console.log([$('li').eq(0).height(),$('li').eq(1).height(),$('li').eq(2).height(),$('li').eq(3).height()]) if(index<50){ return LoadPic(index+1); }else{ return false; } }else{ console.log('wait') } },50)//每隔50ms监听一次 } LoadPic(0);