具有分散效果的瀑布流网页
2016-07-30 18:34
197 查看
具有分散效果的瀑布流网页
这几天在慕课网学习瀑布流,然后学完之后的大作业就是搞这个,“具有分散效果的瀑布流网页”,嗯,没有参考,也没有标准答案,于是我就开始自己来来尝试一下怎么做。首先,在网上找了一下相关的结果,看看有什么可以参考的,一百度,就只找到一篇博客谈到这个效果的,就是下面这篇:带有分散效果的瀑布流(jQuery实现)这篇文章就是讲和我一样的网页效果的。由于博主没有贴动图,我也没有想着去完全依照博主的方法来做,所以我没有运行他的代码(也不知道他的效果具体怎样的),只是粗略的看了一下,了解一下大概的思路。博主的在原有的瀑布流函数的基础上,增加了设置图片初始位置的函数,让图片开始的时候可以分散的摆放。这个想法我觉得很好,所以我就决定按照他的这个思路走下去。然后想了一下自己想要的效果,然后就开始一边写一遍构思代码。
首先是html代码:
split-waterfall.html(比较懒所以css样式就没有分开写了。。。。)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="jQuery-method/js/jquery-1.8.3.min.js"></script> <title>带有分散效果的瀑布流</title> <style type="text/css"> *{ padding: 0; margin: 0; } #main{ position: relative; } .pinF{ padding:15px 0 0 15px; float: left; } .box{ padding: 10px; border:1px solid #cccccc; -webkit-box-shadow: 0 0 6px #ccc; -moz-box-shadow: 0 0 6px #ccc; box-shadow: 0 0 6px #ccc; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .box img{ width: 162px; height: auto; } </style> <script type="text/javascript" src="js3.js"></script> </head> <body> <div id="main"> <div class="pinA pinF"> <div class="box"><img src="images/1.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/2.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/3.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/4.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/5.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/6.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/7.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/8.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/21.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/9.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/10.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/11.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/12.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/13.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/14.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/15.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/16.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/17.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/18.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/19.jpg" alt=""></div> </div> <div class="pinA pinF"> <div class="box"><img src="images/20.jpg" alt=""></div> </div> </div> </body> </html>
这样,页面结构和样式就写完了,接下来是js代码。
经过思考我觉得效果应该是,图片不断加载在窗口的下部的中央的区域里,错乱的摆放好,然后随页面的滚动,图片不断摆放到瀑布流的正确位置,而且图片生成的区域也一直固定在窗口下部中央。
这样的话,就基本需要三个操作函数了,首先第一个是瀑布流的函数,然后是遍历图片的函数,最后是图片具体位置设置的函数。这三个函数,就够了。
遍历图片然后调用设置位置函数的函数——initBox()
这个函数是三个之中最简单的,所以我决定先写。上面说了图片是不断加载在窗口中下部的位置,那如果图片已经设置在瀑布流之中那还要加载在这个地方吗?答案很明显,肯定不行,所以,我们一定要辨别出在瀑布流和不在瀑布流的图片的区别。那怎么区别呢?我用了个比较笨的方法,就是用类名来区分。如果仔细看了我上面页面的代码的话,就可以发现我的id为main的div所有的子级div都有两个类:pinA和pinF。pinF是用来设置样式的,那pinA是用来干嘛的呢?没错,就是用来辨别图片是否在瀑布流之中的标志。用筛选器来选取有pinA类的div,然后遍历这些div来设置位置。然后图片进行了瀑布流之后,我会把pinA这个类从div中去掉,再次调用这个函数就不会选取到瀑布流中的图片了。这样就不用重复渲染已经在瀑布流中图片的位置了。
还有一个问题,我发现已经设置好的位置的图片,如果再调用这个函数的话,那位置岂不是又要变化?这样图片位置不断变动,肯定看的人眼都花了吧。所以必须采用方法,区别出已经设置好位置的图片,然后让它保持在固定位置,然后新加载的图片就按照规则摆好。刚刚用了类名来区别过了,现在怎么办?还用类名吗?(虽然说多类名对HTML文档加载速度没什么影响,但是这个操作还是有点麻烦滴)于是我看到了jQuery的data()方法。这个方法是可以在dom元素绑定一个数据供你使用。具体意思就是我们平时写js对象的时候不是可以后面加个“.”然后绑定一个名称,再往里面添加数据自己用嘛(差不多这个意思理解吧),jQuery的这个方法就是这个用途,不过作用的对象是dom元素而已。你可以用jQuery.hasData()来判断dom元素是否绑定了数据。也可以用data()方法来修改数据值。很方便。于是我就用这个方法来区别设置好的图片和没有设置好的图片。好,到这里这个函数的思路都讲完了,下面是代码:
function initBox(jqObj) {//生成照片初始的位置 var $boxes=jqObj.find('.pinA');//用类名来筛选不在瀑布流的图片 $boxes.each(function () { var $this=$(this); if(jQuery.hasData($this[0])){//用hasData方法来区分没有设置过和已经设置过的照片 setPos($this); //设置过的直接调用函数 }else { $this.data('State','new');//没有设置过的图片是没有data数据的,所以设置数据为“new” setPos($this); } }) }
设置具体图片位置的函数setPos()
上面说过我们设置位置的时候分两种情况:已经设置过的和没有设置过的。我开始的设想是那个图片池是固定在窗口的下部的中央位置的,这种想法很容易联想到用position:fixed的样式来解决,但是,测试过之后我发现,设置成这种样式之后,由于没有其他的内容,导致网页不能滚动起来,而我们的主要函数就是检测网页滚动然后进行瀑布流操作的,所以这种做法并不可行。无奈我只能设置absolute,然后每次图片池都随页面滚动而滚动(然而这样的效果并不好。。。)为了好看,我第一次设置的时候还用了用了fadeIn()和fadeOut()动画。下面是具体代码:
function setPos(jqObj) {//设置图片位置 if(jqObj.data('State')=='new'){//为没设置过位置的图片设置位置 var margin_left = Math.floor(- jqObj.outerWidth() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200)); var margin_top = Math.floor(- jqObj.outerHeight() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200)); jqObj.fadeOut(200);//过度效果 jqObj.css({ "position": "absolute", "top": winHeight*2 + $(window).scrollTop(),//高度为窗口高度加上滚过的高度 "left": winWidth/ 2,//距离左边距离为窗口宽度的一半 "margin-left": margin_left,//设置随机的左边距和上边距达到错乱的效果 "margin-top": margin_top }); jqObj.fadeIn(200);//过渡效果 jqObj.data('State','old')//吧设置好的图片的数据改成‘old’表示这图片已经设置过了 }else if(jqObj.data('State')=='old'){//设置过的图片保持位置,然后随窗口滚动而做滚动动画 jqObj.animate({ top: winHeight + $(window).scrollTop()+'px',//高度为窗口高度加上滚过的高度 left: winWidth/ 2+'px'//距离左边距离为窗口宽度的一半 },0.000001);//这里时间故意设置很短,不然看起来会很卡 } }
瀑布流函数waterfall()
这是就是按照瀑布流方法写的函数,感觉没什么好说的了吧。具体思路可以看注释:
function WaterFall(jqObj) {//瀑布流函数 var wid=jqObj.children().eq(0).outerWidth();//取图片固定的宽度 var cols=Math.floor(winWidth/wid);//算出瀑布流的列数 if(hArr.length<cols){//hArr是全部变量的数组,用来存储瀑布流各类的高度 for (var i=0;i<cols;i++) {//这里循环是为了初始化hArr数组 hArr.push(0); } } jqObj.width(wid*cols).css('margin','0 auto');//设置主体的样式 var Boxes=jqObj.find('.pinA');//筛选没有进入瀑布流的图片 Boxes.each(function (index,value) {//遍历图片设置瀑布流 var h=Boxes.eq(index).outerHeight(); if(index<cols){//每次设置一行数量的图片 var newTop; var newIndex; if($.inArray(0,hArr)>-1){//这里是为了区分第一行的图片和其他行的图片 newTop=hArr[index];//第一行图片的top全部都是0,其他行的话要根据各列图片的高度来确定 newIndex=index; }else{ newTop=Math.min.apply(null,hArr); newIndex=$.inArray(newTop,hArr); } $(value).css({//设置样式 'position':'absolute', 'padding':'15px 0 0 15px', 'margin':'0' }); $(value).animate({//设置移动动画 top:newTop+'px', left:newIndex*wid+"px" },500); $(value).removeClass('pinA'); hArr[newIndex]+=h; } }) }
到这里主要的函数都搞定了,不过我们还要写一个函数用来做判定,来判定什么时候加载新的图片到图片池里,什么时候加载瀑布流,我觉得写两个函数太烦,所以都封装在一个对象里面了:
var loadingCon={//判断函数 loadMin:function () {//比较最短的列的大小和窗口一半的高度,作为是否进行加载新图片的判断依据 if(hArr.length!=0){ var minTop=Math.min.apply(null,hArr); var scrollTop=$(window).scrollTop(); var halfWin=Math.floor(winHeight/2); return minTop-scrollTop<halfWin;//最短列高度超过窗口一半就返回false }else { return true; } }, loadMax:function () {//比较最长的列和窗口高度一半的大小,作为是否进行瀑布流的判断依据 if(hArr.length!=0){ var maxTop=Math.max.apply(null,hArr); var scrollTop=$(window).scrollTop(); var halfWin=Math.floor(winHeight/2); return maxTop-scrollTop<halfWin;//最长列高度超过了窗口一半就返回false }else { return true; } } }
最后来写主要的页面加载函数就大功告成啦:
/** * Created by Homer on 2016/7/29. */ var winHeight=$(window).height(); var winWidth=$(window).width(); var hArr=[]; $(window).on('load',function () { var $main=$("#main"); initBox($main); var dataInt={'data':[{'src':'0.jpg'},{'src':'1.jpg'},{'src':'2.jpg'},{'src':'3.jpg'},{'src':'4.jpg'},{'src':'5.jpg'},{'src':'6.jpg'},{'src':'7.jpg'}]}; $(window).on('scroll',function () { var amount=$main.find('.pinA').length; if(!loadingCon.loadMin()&&amount<6){ $.each(dataInt.data,function (key, value) { var oBox=$('<div>').addClass('pinA').addClass('pinF').appendTo($main); var oPic=$('<div>').addClass('box').appendTo($(oBox)); $('<img>').attr('src','images/P_0'+value.src).appendTo($(oPic)); }) } if (loadingCon.loadMax())WaterFall($main); initBox($main); }) });
至此这个效果就搞定啦(虽然觉得不太完美。。)
其实到这里我也只是完成了半成品而已,还有很多不足的地方,比如窗口往回滚的时候那个图片池会跟着向上滚,然后还有很多不明所以然的闪烁效果。这里给自己一个坑,迟点回来慢慢挖。
其实这篇东西写来也不是打算给别人看的,毕竟我只是个刚入门的小白,还有很多东西都不懂,我写这篇是为了给自己做一个参考,如果你路过看到了,能对你有什么帮助的话,那是我的荣幸;如果里面有什么不正确的内容的话,请一定要留下评论告诉我,我一定很感谢你。
相关文章推荐
- 网页瀑布流效果实现的几种方式
- 网页前端瀑布流布局效果Jquery插件“Masonry”
- 网页瀑布流效果实现的几种方式
- 网页瀑布流效果实现的几种方式
- 详解网页中的瀑布流显示效果
- 20150805 (网页定位导航+瀑布流布局+信息排列)JS+JQuery+CSS3效果实现笔记
- 8款网页瀑布流布局插件(很不错的效果)
- 带有分散效果的瀑布流(jQuery实现)
- 代码最少的网页瀑布流效果
- 网页导航上用CSS标志当前页效果
- 使用HTML CSS实现网页换肤效果(二)
- Js 网站变灰(网页黑白)效果代码(兼…
- jQuery实现悬浮在右上角的网页客服效果代码
- 重构项目之二:使用瀑布流效果加载图片
- js让网页标题闪动效果(记)
- RecylerView完美实现瀑布流效果
- 使用JS实现图片展示瀑布流效果的实例代码
- 在Excel中创建具有双坐标的图表效果
- 如何用css实现网页footer的效果