实例解释瀑布流图的实现原理与方法

2 篇文章 0 订阅
2 篇文章 0 订阅
今天博主上网搜了一下关于瀑布流图的文章,发现实现瀑布流图的方法大概有“通过JS排版”与“通过后台排版”两种。博主认为“通过JS排版”是一种更好的方法,而且网上也是普遍这么认为的。所以博主先简单介绍一下“通过后台排版”的原理,然后在详细说说“通过JS排版”的原理以及实现过程。


原理
通过后台排版:



 
如图,不知道你们看不看得懂……原理就是通过CSS设置出N个纵向的框来,然后在后台输出网页之前,将元素逐个的加到最短的框中去,或者是先填满第一列,在依次填满后面的列,最后输出网页的时候,就是排好版的瀑布流图了!


这种方法将排版的工作交给了网站后台,用户接收到的网页就是排好版的,客户端压力极少,但是因为对网页的排版计算全部交由后台,网页打开之前的空白时间相应增加,很有可能让用户失去打开网页的兴趣。


通过JS排版:
如果通过JS排版的话,博主的方法就是先计算出瀑布流图中元素应当出现的位置,然后通过绝对定位来讲元素放置到相应的位置去。


原理很简单吧?:》


实现


<div id="s_waterFall">
<span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div>
<span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div>
    <span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div>
    <span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div>
    <span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div><span style="white-space:pre">	</span><div class="waterDiv">
<span style="white-space:pre">		</span><!-- HTML content -->
<span style="white-space:pre">	</span></div>
</div>


HTML结构如上,JS定位的只是.waterDiv元素们,而.waterDiv元素的内容是可以随意设置的。

就像下面这样:

<div id="s_waterFall">
	<div class="waterDiv">
		<span>hello</span>
	</div>
	<div class="waterDiv">
		<a href="#">
			<img src="images/2.png" />
			<span>hello</span>
	    </a>
	</div>
	<div class="waterDiv">
		<a href="#">
            <img src="images/3.png" />
		</a>
		<span>hello</span>
	</div>
	<div class="waterDiv">
		<!—HTML Code -->
	</div>
</div>


而因为.waterDiv元素们是通过position:absolute来绝对定位的,所以#s_waterFall在CSS中的position属性就一定要设置为absolute、relative或fixed三个中的一个,至于为什么在CSS Image Map那篇文章中有介绍,这里就不赘述了。


这里我们设置position为relative,这与static(默认值)效果是一样的,并且可以约束内部绝对定位的元素。


#s_waterFall{
width:1300px; /* 宽度 */
margin:100px auto;/* 居中 */
position:relative;
}


然后我们设置.waterDiv的属性:

.waterDiv{
width:230px; /* 每一列的宽度 */
box-shadow:-3px 3px 5px #111;/* 视觉效果 */
border:solid #999 1px;/* 视觉效果 */
position:absolute;/* 设置为绝对定位 */
}


接下来就是JS代码了!


首先我们要将JS代码放在一个自动执行的匿名函数中:
(function(){
/* JavaScript Code */
}())


很多插架甚至框架都是这么做的,这样做的好处有很多,其中一个好处就是我们的变量什么的不会污染别人代码或插件的命名空间。其他的我会在以后再写一篇文章来说,这里就不赘述了。


这个插件现在是可以设置父元素的宽度(total_width),列数(col_num),列宽(col_width),瀑布流子元素的类名称(kid_class),两个子元素之间的间距(margin_vertical)。一开始直接写死为四列的。可能用现在这个版本来介绍的话会比较难理解,但是一开始的版本我忘了保存……所以就直接拿这个来说吧:》


在JS代码中一个好习惯是在函数作用域中把用到的变量在作用域头部全部声明一遍。所以我们先生命变量:

/* config area start*/
var total_width = 1300;
//瀑布流图父元素的宽度,用来计算列之间距离,不是设置父元素宽度
var col_num = 4;//设置列数
var col_width = 230;//设置列宽
var kid_class = "waterDiv";//设置瀑布流图子元素的类名
var margin_vertical = 20;//设置瀑布流图子元素的垂直间距
/* config area end*/

/* ↑ for users ↑ */
/* check start */
if( col_num * col_width > total_width){
//如果列数过多,影响显示效果,会在console中提醒
console.log("Warning : Father div is too small !!!!"); 
}

/* check end */

/* variables start */
var col_heights = new Array(col_num);//生成用来记录当前列长度的数组
for(i = 0; i < col_heights.length; i++){ //将数组元素值置为0
col_heights[i] = 0;
}
var min_col = 0;//遍历时,当前长度最小的列在数组中的的索引值
var top_int = 0;//遍历时,当前元素应设置的绝对定位top值
var left_int = 0;//遍历时,当前元素应设置的绝对定位left值
var i; //for循环计数变量
var str = ""; //空的字符串变量
var margin_horizontal = ( total_width - col_num * col_width ) / ( col_num * 2 );
//自动计算列之间距离
/* variables end*/


然后我们遍历所有的.waterDiv元素,当遍历到某个元素时,先找出目前最短的一列,这就是我们要添加元素的一列,然后我们计算出该元素绝对定位的top与left值,赋给该元素,这样在视觉上,该元素就附加在了最短的一列上了,最后不要忘了更新该列的当前长度啊!


$("." + kid_class).each(function(){ //遍历所有.waterDiv并设置top与left值
min_col = minOfArray(col_heights);//获取当前长度最小的列的索引值
top_int = col_heights[min_col];//当前元素应设置的绝对定位top值


left_int = margin_horizontal + ( col_width + margin_horizontal * 2 ) * min_col;//计算当前元素应设置的绝对定位left值


$(this).css("top", top_int + "px");//对top, left进行设置
$(this).css("left", left_int + "px");//"px"不要忘记加啊!
col_heights[min_col] += $(this).height() + margin_vertical;//更新列的长度
});

function minOfArray(col_array){
//这是一个找出数组中最小的元素,并返回该元素索引的函数,就是在上一段代码中调用的。
/* 
* input : Array of numbers
* output: the index of minimal number.
*/
var min_num = col_array[0];
var min_index = 0;
for(var i = 0; i < col_array.length; i++){
if(col_array[i] < min_num){
min_num = col_array[i];
min_index = i;
}
}

return min_index;
}


这样,打开网页,一个瀑布流图的demo就做好了!如果不能运行,检查一下是不是忘了引用jQuery库了?:》
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值