最近做了一个瀑布流效果,思路很简单
首先计算屏幕一行可以放多少个图片,然后在第二行开始,计算每一列的高度并取出最小值,将新图片加载在最小列高度下,如此循环,并且设定一个条件,当滑动到一定距离后,开始重新加载。当然中间我们可以加上一些动画效果,让网页看起来更炫酷一些。
html‘比较简单,这里用了li元素,给每个li外围设置了padding,内部容器设定颜色,以达成元素间隔效果,这样避免了使用maring元素最后一个还要特殊处理,当然我们还可以通过给ul设置负的margin值来解决这个问题,不过由于后面要进行很多处理所以设置了padding。
<div class="container"> <ul> <!-- <li> <div class=‘wrap‘> <div class="img"> <img src="images/1.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/2.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/3.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/4.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/5.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/6.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/7.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/8.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/9.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/10.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li> <li> <div class=‘wrap‘> <div class="img"> <img src="images/11.jpg" /> </div> <div class="text">瀑布流测试demo</div> </div> </li>--> </ul> </div>
中间的li列表隐藏掉了,可有可无,效果都一样。
下面主要是js;
var number=0; var sindex=0; var arr=[]; //存放每列高度的数组 calc() var data = [ {‘src‘:‘1.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘2.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘3.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘4.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘5.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘6.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘7.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘8.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘9.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘10.jpg‘,‘title‘:‘瀑布流测试‘}, {‘src‘:‘11.jpg‘,‘title‘:‘瀑布流测试‘} ];
第一步设定了变量,number为每个元素的索引,arr为存储每列高度数组,并通过data数组来模拟加载。calc是执行计算的函数。
1 window.onscroll=function(){ 2 if($(window).scrollTop()+$(window).height()+20>$(document).height()){ 3 //alert(23) 4 $.each(data,function(i,val){ 5 var sHtml=‘<li><div class="wrap"><div class="img"><img src="images/‘+val.src+‘"/></div>‘ 6 sHtml+=‘<div class="text">‘+val.title+number+‘</div></div></li>‘ 7 $("ul").append(sHtml) 8 number++ 9 }) 10 calc() 11 } 12 } 13 window.onload=function(){ 14 //alert(23) 15 $.each(data,function(i,val){ 16 var sHtml=‘<li><div class="wrap"><div class="img"><img src="images/‘+val.src+‘"/></div>‘ 17 sHtml+=‘<div class="text">‘+val.title+number+‘</div></div></li>‘ 18 $("ul").append(sHtml) 19 number++ 20 }) 21 setTimeout(calc,10) 22 }
在页面加载,页面滚动到下部时,我们循环生成li元素,并且执行calc方法,在页面加载时,对calc函数进行了延时处理,如果直接执行,会出现计算错误,不知道还有没有更好的办法解决。
1 function calc(){ 2 var $_li=$(‘li‘); 3 var length=$_li.length; 4 var li_width=$("li").eq(0).outerWidth(); 5 var pad_width=$("li").eq(0).width(); 6 var documentWidth=$(window).width(); 7 var column=Math.floor(documentWidth/li_width); //每一行可显示的图片数 8 $("ul").css("width",column*li_width) ; //计算外围容器宽度 9 for(i=sindex;i<length;i++){ 10 if(i<column){ //第一列图片正常排列 11 arr[i]=$_li.eq(i).outerHeight(); 12 $_li.eq(i).css({"position":‘absolute‘, //元素设为绝对定位 13 "left":i*li_width, 14 "top":100, 15 "opacity":"0", 16 ‘width‘:"0px" 17 }).addClass("ani") 18 $_li.eq(i).animate({ 19 opacity:"1", 20 top:"0px", 21 left:i*li_width, 22 width:pad_width 23 },700) 24 }else{ 25 var minHeight=Math.min.apply(null,arr) //计算最小高度确定位置 26 //console.log(arr) 27 var index=compare(minHeight,arr); 28 put($_li,i,index,column,minHeight) 29 arr[index]+=$_li.eq(i).outerHeight() 30 } 31 console.log(minHeight) 32 } 33 sindex=length 34 35 }
主要的元素,calc元素,通过屏幕宽度与li宽度进行每行可放置li的数量,其中第一行的元素直接赋值,每个元素的left为别为i*300,其中有些属性查了些资料才弄清楚。
jquery中获取元素宽度为width(),这个宽度只包括元素的width部分,而outerWidth()获取的宽度包括元素的padding与border,outerWidth(true)则默认包括margin。
在js中对应为offsetWidth。
获取元素相对于文档(document)的距离在jquery方法分别为offset().top,offset().left,js中为offsetHeight,offsetLeft。
在排列过程,我添加了透明度+top值得动画,同时运用css3属性进行了反转动画(scale(-1,1)效果等同于rotateY(180)).
在calc中运用了方法compare与put。如下:
1 function compare(height,sum){ 2 var $_length=sum.length; 3 for(j=0;j<$_length;j++){ 4 if(sum[j]==height){ 5 return j 6 } 7 } 8 } 9 function put(obj,index,minIndex,column,height){ 10 obj.eq(index).css({"position":‘absolute‘, //元素设为绝对定位 11 "left":obj.eq(Math.floor(column/2)).css("left"), 12 "top":parseInt(height)+100, 13 "opacity":"0", 14 ‘width‘:"0px" 15 }).addClass("ani") 16 obj.eq(index).stop().animate({ 17 opacity:"1", 18 top:height, 19 left:obj.eq(minIndex).css("left"), 20 width:"280px" 21 },700) 22 }
css写的比较随意:
<style> *{margin:0px;padding:0px} body,html{background-color:#F5F5DC} .container{margin:0px auto} ul{margin:20px auto;width:auto;position:relative} li{list-style-type:none;width:280px;padding:10px;float:left;margin-top:10px} .wrap{background-color:#fff;box-shadow:5px 5px 10px #ccc;border-radius:10px;} .img{padding:10px} .img img{width:260px;border-radius:10px} .text{height:40px;line-height:40px;text-align:center;font-family:"微软雅黑";font-size:18px} .img img:hover{-webkit-animation:fadein ease-in-out 1s;-moz-animation:fadein ease-in-out 1s;-ms-animation:fadein ease-in-out 1s;-o-animation:fadein ease-in-out 1s} .ani{-webkit-animation:scale 1s ease-in-out;-moz-animation:scale 1s ease-in-out;-ms-animation:scale 1s ease-in-out;-o-animation:scale 1s ease-in-out} @-webkit-keyframes fadein{ 0%{opacity:1} 20%{opacity:0.5} 100%{opacity:1} } @-moz-keyframes fadein{ 0%{opacity:1} 20%{opacity:0.5} 100%{opacity:1} } @-ms-keyframes fadein{ 0%{opacity:1} 20%{opacity:0.5} 100%{opacity:1} } @-o-keyframes fadein{ 0%{opacity:1} 20%{opacity:0.5} 100%{opacity:1} } @-webkit-keyframes scale{ 0%{-webkit-transform:scale(-1,1)} 50%{-webkit-transform:scale(1,1)} } @-moz-keyframes scale{ from{-moz-transform:scale(-1,1)} to{-moz-transform:scale(1,1)} } @-ms-keyframes scale{ from{-ms-transform:scale(-1,1)} to{-ms-transform:scale(1,1)} } @-o-keyframes scale{ from{-o-transform:scale(-1,1)} to{-o-transform:scale(1,1)} } </style>
本来想按面向对象方向写,写着写着又写成了乱七八糟,没有专门学过编程,还是非常欠缺这个细胞的a ,努力吧!
有错误欢迎随时指出。