JavaScript实现自适应宽度的瀑布流

摘要: 主要介绍瀑布流的一种实现方法:绝对定位(css)+javascript+ajax+json。简单一点如果不做滚动加载的话就是绝对定位(css)+javascript了,ajax和json是滚动加载更多内容的时候用到的。

 

       这样的布局并不陌生,从2011年Pinterest创立以来,中国互联网就迅速掀起了一股模仿Pinterest的热潮,国内有众多网站采用瀑布流的布局方式,例如花瓣网、美丽说等等。而事实上在中国互联网,模仿一些在国外被人看好的模式(当然,你也可以说是山寨或抄袭,呵呵!!)向来都是一个不错的idea。

 

  OK,现在进入正题。这里主要介绍瀑布流的一种实现方法:绝对定位(css)+javascript+ajax+json。简单一点如果不做滚动加载的话就是绝对定位(css)+javascript了,ajax和json是滚动加载更多内容的时候用到的。

 

  下面是实现思路:

 

  1、计算页面的宽度,计算出页面可放数据块的列数(如上图所示就有6列)。

  2、将各个数据块的高度尺寸记入数组中(需要等所有图片加载完成,否则无法知道图片的高度)。

  3、用绝对定位先将页面第一行填满,因为第一行的top位置都是一样的,然后用数组记录每一列的总高度。

  4、继续用绝对定位将其他数据块定位在最短的一列的位置之后然后更新该列的高度。

  5、当浏览器窗口大小改变时,重新执行一次上面1-4步以重新排放(列数随页面宽度而改变,因而需要重新排放)。

  6、滚动条滚动到底部时加载新的数据进来后也是定位在最短的一列的位置之后然后更新该列的高度。

 

  思路有了,然后就是如何用代码实现。当然,如果看完以上的6个步骤你已经知道如何实现,那么下面的内容大可不必细看。

 

  首先在页面上写好基本的HTML和CSS(为方便起见,CSS就不外联了),代码如下:

 
 1 DOCTYPE html>2  <html>3      <head>4          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">5          <title>瀑布流布局title>6          <style type="text/css">7              body{margin:0; font-family:微软雅黑;}8              #flow-box{margin:10px auto 0 auto; padding:0; position:relative}9              #flow-box li{
10                  width:190px; position:absolute; padding:10px; border:solid 1px #efefef; list-style:none; 
11                  opacity:0;
12                  -moz-opacity:0;
13                  filter:alpha(opacity=0);
14                  -webkit-transition:opacity 500ms ease-in-out;
15                  -moz-transition:opacity 500ms ease-in-out;
16                  -o-transition:opaicty 500ms ease-in-out;
17                  transition:opaicty 500ms ease-in-out;}
18              #flow-box li img{width:100%;}
19              #flow-box li a{display:block; width:100%; text-align:center; font-size:14px; color:#333; line-height:18px; margin-top:10px; text-decoration:none;}
20              .loadwrap{position:absolute; left:0; width:100%; text-align:center;}
21          style>
22      head>
23      <body>
24          <ul id="flow-box">
25              <li><img src="http://www.mitxiong.com/NewsImages/2012121821504156.jpg" /><a href="#">图片标题1a>li> 26 <li><img src="http://www.mitxiong.com/NewsImages/2012112718241731.jpg" /><a href="#">图片标题2a>li> 27 <li><img src="http://www.mitxiong.com/NewsImages/2012111806582944.jpg" /><a href="#">图片标题3a>li> 28 <li><img src="http://www.mitxiong.com/NewsImages/2012110907231232.jpg" /><a href="#">图片标题4a>li> 29 <li><img src="http://www.mitxiong.com/NewsImages/2012110406319529.jpg" /><a href="#">图片标题5a>li> 30 <li><img src="http://www.mitxiong.com/NewsImages/2012101808066955.jpg" /><a href="#">图片标题6a>li> 31 <li><img src="http://www.mitxiong.com/NewsImages/2012101307276582.jpg" /><a href="#">图片标题7a>li> 32 <li><img src="http://www.mitxiong.com/NewsImages/2012082223432719.jpg" /><a href="#">图片标题8a>li> 33 <li><img src="http://www.mitxiong.com/NewsImages/2012082121509065.jpg" /><a href="#">图片标题9a>li> 34 <li><img src="http://www.mitxiong.com/NewsImages/2012081922387254.jpg" /><a href="#">图片标题10a>li> 35 <li><img src="http://www.mitxiong.com/NewsImages/2012081700252403.jpg" /><a href="#">图片标题11a>li> 36 <li><img src="http://www.mitxiong.com/NewsImages/2012081407597304.jpg" /><a href="#">图片标题12a>li> 37 <li><img src="http://www.mitxiong.com/NewsImages/2012081218248259.jpg" /><a href="#">图片标题13a>li> 38 <li><img src="http://www.mitxiong.com/NewsImages/2012080621278799.jpg" /><a href="#">图片标题14a>li> 39 <li><img src="http://www.mitxiong.com/NewsImages/2012072907484455.jpg" /><a href="#">图片标题15a>li> 40 <li><img src="http://www.mitxiong.com/NewsImages/2012072521564314.jpg" /><a href="#">图片标题16a>li> 41 <li><img src="http://www.mitxiong.com/NewsImages/2012072507238259.jpg" /><a href="#">图片标题17a>li> 42 <li><img src="http://www.mitxiong.com/NewsImages/2012072409035684.jpg" /><a href="#">图片标题18a>li> 43 <li><img src="http://www.mitxiong.com/NewsImages/2012072219405236.jpg" /><a href="#">图片标题19a>li> 44 <li><img src="http://www.mitxiong.com/NewsImages/2012071218416980.jpg" /><a href="#">图片标题20a>li> 45 ul> 46 <div id="loadimg" class="loadwrap"><img src="Images/load.jpg" />div> 47 body> 48 html>
 

  以上代码非常简单,可以看出页面最初将会先加载20个数据块。值得一提的是在CSS里面定义了opacity为0,目的是在数据块未排放好之前先隐藏起来,排放好后再将opacity设为1显示出来,另外这里用了css3的transition做一点体验上的升级;还有一点就是可以看到页面底部有一个id为“loading”的DIV,用来表示数据正在加载中。下面开始用JS实现以上思路(6个步骤)。

 

  1、计算页面的宽度,计算出页面可放数据块的列数

 
 1 <script type="text/javascript">2     function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3         var w = document.documentElement.offsetWidth;//计算页面宽度4         var ul = document.getElementById("flow-box");5         var li = ul.getElementsByTagName("li");6         var iw = li[0].offsetWidth + mh;//计算数据块的宽度7         var c = Math.floor(w / iw);//计算列数8         ul.style.width = iw * c - mh + "px";//设置ul的宽度至适合便可以利用css定义的margin把所有内容居中 
9 } 10 script>
 

  注释写得非常明白,这一步不说应该都很容易懂。

 

  2、将各个数据块的高度尺寸记入数组中

 
 1 <script type="text/javascript">2     function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3         //... 省略上一步的部份代码 ...8         ul.style.width = iw * c - mh + "px";//设置ul的宽度至适合便可以利用css定义的margin把所有内容居中9                 
10         var liLen = li.length;
11         var lenArr = [];
12         for (var i = 0; i < liLen; i++) {//遍历每一个数据块将高度记入数组
13             lenArr.push(li[i].offsetHeight);
14         }
15     }
16 script>
 

  由于数据块里面含有图片,也没有给定图片的尺寸,所以需要等待图片加载完成后方可获取其高度;那么可以在window.onload的时候调用flow方法。代码变成:

 
 1 <script type="text/javascript">2     function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3         //... 省略上一步的部份代码 ...8         ul.style.width = iw * c - mh + "px";//设置ul的宽度至适合便可以利用css定义的margin把所有内容居中9                 
10         var liLen = li.length;
11         var lenArr = [];
12         for (var i = 0; i < liLen; i++) {//遍历每一个数据块将高度记入数组
13             lenArr.push(li[i].offsetHeight);
14         }
15     }
16     //图片加载完成后执行
17     window.onload = function() {flow(10, 10)};
18 script>
 

  3、用绝对定位先将页面第一行填满,因为第一行的top位置都是一样的,然后用数组记录每一列的总高度。

 
 1 <script type="text/javascript">2             function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离//... 省略上一步的部份代码 ...
12 for (var i = 0; i < liLen; i++) {//遍历每一个数据块将高度记入数组 13 lenArr.push(li[i].offsetHeight); 14 } 15 16 var oArr = []; 17 for (var i = 0; i < c; i++) {//把第一行排放好,并将每一列的高度记入数据oArr 18 li[i].style.top = "0"; 19 li[i].style.left = iw * i + "px"; 20 li[i].style.opacity = "1"; 21 li[i].style["-moz-opacity"] = "1"; 22 li[i].style["filter"] = "alpha(opacity=100)"; 23 oArr.push(lenArr[i]); 24 } 25 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//将loading移到下面 26 } 27 //图片加载完成后执行 28 window.onload = function() {flow(10, 10)}; 29 //获取数字数组的最大值 30 function _getMaxValue(arr) { 31 var a = arr[0]; 32 for (var k in arr) { 33 if (arr[k] > a) { 34 a = arr[k]; 35 } 36 } 37 return a; 38 } 39 script>
 

   截至目前为止,可以到浏览器里面预览一下效果:

 

 

 

OK,接下来开始放置其他的数据块了,也就是到思路的第4步了。

 

4、继续用绝对定位将其他数据块定位在最短的一列的位置之后然后更新该列的高度。

 

 
 1 <script type="text/javascript">2              function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3                  //... 省略上一步的部份代码 ...
17 for (var i = 0; i < c; i++) {//把第一行排放好,并将每一列的高度记入数据oArr 18 li[i].style.top = "0"; 19 li[i].style.left = iw * i + "px"; 20 li[i].style.opacity = "1"; 21 li[i].style["-moz-opacity"] = "1"; 22 li[i].style["filter"] = "alpha(opacity=100)"; 23 oArr.push(lenArr[i]); 24 } 25 26 for (var i = c; i < liLen; i++) {//将其他数据块定位到最短的一列后面,然后再更新该列的高度 27 var x = _getMinKey(oArr);//获取最短的一列的索引值 28 li[i].style.top = oArr[x] + mv + "px"; 29 li[i].style.left = iw * x + "px"; 30 li[i].style.opacity = "1"; 31 li[i].style["-moz-opacity"] = "1"; 32 li[i].style["filter"] = "alpha(opacity=100)"; 33 oArr[x] = lenArr[i] + oArr[x] + mv;//更新该列的高度 34 } 35 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//将loading移到下面 36 } 37 //图片加载完成后执行 38 window.onload = function() {flow(10, 10)}; 39 //获取数字数组的最大值 40 function _getMaxValue(arr) { 41 //... 省略部份代码 ...
48 } 49 //获取数字数组最小值的索引 50 function _getMinKey(arr) { 51 var a = arr[0]; 52 var b = 0; 53 for (var k in arr) { 54 if (arr[k] < a) { 55 a = arr[k]; 56 b = k; 57 } 58 } 59 return b; 60 } 61 script>
 

 

  到这一步可以到浏览器里面再看一次效果,可以说整个瀑布流的雏形都出来了:

 

 

 

 

 

 

 

 

 

 

  5、当浏览器窗口大小改变时,重新执行一次上面1-4步以重新排放

 

 

 

  这一步操作起来也相当便捷,在改变窗口大小时,再执行一次flow方法即可

 

 
 1 <script type="text/javascript">2              function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3              //... 省略部份代码 ...
37 //图片加载完成后执行 38 window.onload = function() {flow(10, 10)}; 39 //改变窗口大小时重新布局 40 var re; 41 window.onresize = function() { 42 clearTimeout(re); 43 re = setTimeout(function() {flow(10, 10);}, 200); 44 } 45 //获取数字数组的最大值 46 function _getMaxValue(arr) { 47 //... 省略部份代码 ...
54 } 55 //获取数字数组最小值的索引 56 function _getMinKey(arr) { 57 //... 省略部分代码 ...
66 } 67 script>
 

 

  这里值得注意的便是setTimeout,由于onresize的触发频率非常高,用setTimout设定一个间隔时间可以减低flow方法的执行频率,降低性能损耗。

 

 

 

  6、滚动条滚动到底部时加载新的数据进来后也是定位在最短的一列的位置之后然后更新该列的高度。

 

 
  1 <script type="text/javascript">2              function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离3                 //... 省略部份代码 ... 
35 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//将loading移到下面36 37 function scroll() {//滚动加载数据38 var st = oArr[_getMinKey(oArr)];39 var scrollTop = document.documentElement.scrollTop > document.body.scrollTop? document.documentElement.scrollTop : document.body.scrollTop;40 if (scrollTop >= st - document.documentElement.clientHeight) {41 window.onscroll = null;//为防止重复执行,先清除事件42 _request(null, "GetList.php", function(data) {//当滚动到达最短的一列的距离时便发送ajax请求新的数据,然后执行回调函数43 _addItem(data.d, function() {//追加数据44 var liLenNew = li.length;45 for(var i = liLen; i < liLenNew; i++) {46 lenArr.push(li[i].offsetHeight);47 }48 for(var i = liLen; i < liLenNew; i++) {49 var x = _getMinKey(oArr);50 li[i].style.top = oArr[x] + 10 + "px";51 li[i].style.left = iw * x + "px";52 li[i].style.opacity = "1";53 li[i].style["-moz-opacity"] = "1";54 li[i].style["filter"] = "alpha(opacity=100)";55 oArr[x] = lenArr[i] + oArr[x] + 10;56 }57 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//loading向下移位58 liLen = liLenNew;59 window.onscroll = scroll;//执行完成,恢愎onscroll事件60 });61 })62 }63 }64 window.onscroll =scroll;65 }66 //图片加载完成后执行67 window.onload = function() {flow(10, 10)};68 //... 省略部份代码 ...
74 //追加项75 function _addItem(arr, callback) {76 var _html = "";77 var a = 0;78 var l = arr.length;79 (function loadimg() {80 var img = new Image();81 img.onload = function() {82 a += 1;83 if (a == l) {84 for (var k in arr) {85 var img = new Image();86 img.src = arr[k].img;87 _html += '
  • ' + arr[k].img + '" />' + arr[k].title + '
';88                              }89                              _appendhtml(document.getElementById("flow-box"), _html);90                              callback();91                          }92                          else {93                              loadimg();94                          }95                      }96                      img.src = arr[a].img;97                  })()98              }99              //ajax请求
100             function _request(reqdata, url, callback) {
101                 var xmlhttp;
102                 if (window.XMLHttpRequest) {
103                     xmlhttp = new XMLHttpRequest();
104                 }
105                 else {
106                     xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
107                 }
108                 xmlhttp.onreadystatechange = function () {
109                     if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
110                         var data = eval("(" + xmlhttp.responseText + ")");
111                         callback(data);
112                     }
113                 }
114                 xmlhttp.open("POST", url);
115                 xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
116                 xmlhttp.send(reqdata);
117             }
118             //追加html
119             function _appendhtml(parent, child) {
120                 if (typeof (child) == "string") {
121                     var div = document.createElement("div");
122                     div.innerHTML = child;
123                     var frag = document.createDocumentFragment();
124                     (function() {
125                         if (div.firstChild) {
126                             frag.appendChild(div.firstChild);
127                             arguments.callee();
128                         }
129                         else {
130                             parent.appendChild(frag);
131                         }
132                     })();
133                 }
134                 else {
135                     parent.appendChild(child);
136                 }
137             }
138              //获取数字数组的最大值
139              function _getMaxValue(arr) {
140                  //... 省略部份代码 ...
147 } 148 //获取数字数组最小值的索引 149 function _getMinKey(arr) { 150 //... 省略部份代码 ...
159 } 160 script>
 

 

  这一步涉及的代码比较多,简单概括其实就是多了几个方法:scroll()、_addItem()、_request()、_appendhtml()。

 

      主要是看scroll()。在这里_addItem()和_requeat()是供scroll()调用的,而_appendhtml()是供_addItem()调用的。

 

 

 

  这一步的整个过程是:当页面滚动到最短的一列数据的底部时就发出ajax请求加载新的数据,然后待数据中的图片全部load完后就追加到页面上,然后将这些数据项的高度写入到数组lenArr中,并对新加入的这些数据项进行定位,按照每一项都放在最短列的后面的规则而排放在适当的位置上,最后再将loading图片向下移到最底部的位置。

 

 

 

  总结以上的整个思路,有4个地方值得一说:

 

 

 

  1、缩放浏览器窗口时,onresize的触发很频繁,为降低性能损耗,需要待缩放结束后再执行重排,以上思路是使用setTimeout来处理。

 

 

 

  2、页面滚动到最下面加载新数据的时候,只需对新数据排列。

 

 

 

  3、以上思路中加载新数据要等图片都加载完成后才知道其高度,但实际项目中最好是服务器能给定高度值。

 

 

 

  4、滚动触发加载新数据时,要避免事件多次触发,以上思路是将onscroll事件置为空,加载完成后再将事件恢复。

 

 

 

  最后附上完整的代码:

 

 

 

  flow.html

 

 <!DOCTYPE html>2  <html>3      <head>4          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">5          <title>瀑布流布局</title>6          <style type="text/css">7              body{margin:0; font-family:微软雅黑;}8              #flow-box{margin:10px auto 0 auto; padding:0; position:relative}9              #flow-box li{10                  width:190px; position:absolute; padding:10px; border:solid 1px #efefef; list-style:none; 11                  opacity:0;12                  -moz-opacity:0;13                  filter:alpha(opacity=0);14                  -webkit-transition:opacity 500ms ease-in-out;15                  -moz-transition:opacity 500ms ease-in-out;16                  -o-transition:opaicty 500ms ease-in-out;17                  transition:opaicty 500ms ease-in-out;}18              #flow-box li img{width:100%;}19              #flow-box li a{display:block; width:100%; text-align:center; font-size:14px; color:#333; line-height:18px; margin-top:10px; text-decoration:none;}20              .loadwrap{position:absolute; left:0; width:100%; text-align:center;}21          </style>22      </head>23      <body>24          <ul id="flow-box">25              <li><img src="http://www.mitxiong.com/NewsImages/2012121821504156.jpg" /><a href="#">图片标题1</a></li>26              <li><img src="http://www.mitxiong.com/NewsImages/2012112718241731.jpg" /><a href="#">图片标题2</a></li>27              <li><img src="http://www.mitxiong.com/NewsImages/2012111806582944.jpg" /><a href="#">图片标题3</a></li>28              <li><img src="http://www.mitxiong.com/NewsImages/2012110907231232.jpg" /><a href="#">图片标题4</a></li>29              <li><img src="http://www.mitxiong.com/NewsImages/2012110406319529.jpg" /><a href="#">图片标题5</a></li>30              <li><img src="http://www.mitxiong.com/NewsImages/2012101808066955.jpg" /><a href="#">图片标题6</a></li>31              <li><img src="http://www.mitxiong.com/NewsImages/2012101307276582.jpg" /><a href="#">图片标题7</a></li>32              <li><img src="http://www.mitxiong.com/NewsImages/2012082223432719.jpg" /><a href="#">图片标题8</a></li>33              <li><img src="http://www.mitxiong.com/NewsImages/2012082121509065.jpg" /><a href="#">图片标题9</a></li>34              <li><img src="http://www.mitxiong.com/NewsImages/2012081922387254.jpg" /><a href="#">图片标题10</a></li>35              <li><img src="http://www.mitxiong.com/NewsImages/2012081700252403.jpg" /><a href="#">图片标题11</a></li>36              <li><img src="http://www.mitxiong.com/NewsImages/2012081407597304.jpg" /><a href="#">图片标题12</a></li>37              <li><img src="http://www.mitxiong.com/NewsImages/2012081218248259.jpg" /><a href="#">图片标题13</a></li>38              <li><img src="http://www.mitxiong.com/NewsImages/2012080621278799.jpg" /><a href="#">图片标题14</a></li>39              <li><img src="http://www.mitxiong.com/NewsImages/2012072907484455.jpg" /><a href="#">图片标题15</a></li>40              <li><img src="http://www.mitxiong.com/NewsImages/2012072521564314.jpg" /><a href="#">图片标题16</a></li>41              <li><img src="http://www.mitxiong.com/NewsImages/2012072507238259.jpg" /><a href="#">图片标题17</a></li>42              <li><img src="http://www.mitxiong.com/NewsImages/2012072409035684.jpg" /><a href="#">图片标题18</a></li>43              <li><img src="http://www.mitxiong.com/NewsImages/2012072219405236.jpg" /><a href="#">图片标题19</a></li>44              <li><img src="http://www.mitxiong.com/NewsImages/2012071218416980.jpg" /><a href="#">图片标题20</a></li>45          </ul>46          <div id="loadimg" class="loadwrap"><img src="Images/load.jpg" /></div>47          <script type="text/javascript">48              function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离49                  var w = document.documentElement.offsetWidth;//计算页面宽度50                  var ul = document.getElementById("flow-box");51                  var li = ul.getElementsByTagName("li");52                  var iw = li[0].offsetWidth + mh;//计算数据块的宽度53                  var c = Math.floor(w / iw);//计算列数54                  ul.style.width = iw * c - mh + "px";//设置ul的宽度至适合便可以利用css定义的margin把所有内容居中55                  56                  var liLen = li.length;57                  var lenArr = [];58                  for (var i = 0; i < liLen; i++) {//遍历每一个数据块将高度记入数组59                      lenArr.push(li[i].offsetHeight);60                  }61                  62                  var oArr = [];63                  for (var i = 0; i < c; i++) {//把第一行排放好,并将每一列的高度记入数据oArr64                      li[i].style.top = "0";65                      li[i].style.left = iw * i + "px";66                      li[i].style.opacity = "1";67                      li[i].style["-moz-opacity"] = "1";68                      li[i].style["filter"] = "alpha(opacity=100)";69                      oArr.push(lenArr[i]);70                  }71                  72                  for (var i = c; i < liLen; i++) {//将其他数据块定位到最短的一列后面,然后再更新该列的高度73                      var x = _getMinKey(oArr);//获取最短的一列的索引值74                      li[i].style.top = oArr[x] + mv + "px";75                      li[i].style.left = iw * x + "px";76                      li[i].style.opacity = "1";77                      li[i].style["-moz-opacity"] = "1";78                      li[i].style["filter"] = "alpha(opacity=100)";79                      oArr[x] = lenArr[i] + oArr[x] + mv;//更新该列的高度80                  }81                 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//将loading移到下面82                 83                 function scroll() {//滚动加载数据84                     var st = oArr[_getMinKey(oArr)];85                     var scrollTop = document.documentElement.scrollTop > document.body.scrollTop? document.documentElement.scrollTop : document.body.scrollTop;86                     if (scrollTop >= st - document.documentElement.clientHeight) {87                         window.onscroll = null;//为防止重复执行,先清除事件88                         _request(null, "GetList.php", function(data) {//当滚动到达最短的一列的距离时便发送ajax请求新的数据,然后执行回调函数89                             _addItem(data.d, function() {//追加数据90                                 var liLenNew = li.length;91                                 for(var i = liLen; i < liLenNew; i++) {92                                     lenArr.push(li[i].offsetHeight);93                                 }94                                 for(var i = liLen; i < liLenNew; i++) {95                                     var x = _getMinKey(oArr);96                                     li[i].style.top = oArr[x] + 10 + "px";97                                     li[i].style.left = iw * x + "px";98                                     li[i].style.opacity = "1";99                                     li[i].style["-moz-opacity"] = "1";
100                                     li[i].style["filter"] = "alpha(opacity=100)";
101                                     oArr[x] = lenArr[i] + oArr[x] + 10;
102                                 }
103                                 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//loading向下移位
104                                 liLen = liLenNew;
105                                 window.onscroll = scroll;//执行完成,恢愎onscroll事件
106                             });
107                         })
108                     }
109                 }
110                 window.onscroll =scroll;
111              }
112              //图片加载完成后执行
113              window.onload = function() {flow(10, 10)};
114              //改变窗口大小时重新布局
115               var re;
116               window.onresize = function() {
117                    clearTimeout(re);
118                    re = setTimeout(function() {flow(10, 10);}, 200);
119               }
120              //追加项
121              function _addItem(arr, callback) {
122                  var _html = "";
123                  var a = 0;
124                  var l = arr.length;
125                  (function loadimg() {
126                      var

转自:html5中国(http://www.html5cn.org/article-4652-3.html)
  1 <!DOCTYPE html>2  <html>3      <head>4          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">5          <title>瀑布流布局</title>6          <style type="text/css">7              body{margin:0; font-family:微软雅黑;}8              #flow-box{margin:10px auto 0 auto; padding:0; position:relative}9              #flow-box li{10                  width:190px; position:absolute; padding:10px; border:solid 1px #efefef; list-style:none; 11                  opacity:0;12                  -moz-opacity:0;13                  filter:alpha(opacity=0);14                  -webkit-transition:opacity 500ms ease-in-out;15                  -moz-transition:opacity 500ms ease-in-out;16                  -o-transition:opaicty 500ms ease-in-out;17                  transition:opaicty 500ms ease-in-out;}18              #flow-box li img{width:100%;}19              #flow-box li a{display:block; width:100%; text-align:center; font-size:14px; color:#333; line-height:18px; margin-top:10px; text-decoration:none;}20              .loadwrap{position:absolute; left:0; width:100%; text-align:center;}21          </style>22      </head>23      <body>24          <ul id="flow-box">25              <li><img src="http://www.mitxiong.com/NewsImages/2012121821504156.jpg" /><a href="#">图片标题1</a></li>26              <li><img src="http://www.mitxiong.com/NewsImages/2012112718241731.jpg" /><a href="#">图片标题2</a></li>27              <li><img src="http://www.mitxiong.com/NewsImages/2012111806582944.jpg" /><a href="#">图片标题3</a></li>28              <li><img src="http://www.mitxiong.com/NewsImages/2012110907231232.jpg" /><a href="#">图片标题4</a></li>29              <li><img src="http://www.mitxiong.com/NewsImages/2012110406319529.jpg" /><a href="#">图片标题5</a></li>30              <li><img src="http://www.mitxiong.com/NewsImages/2012101808066955.jpg" /><a href="#">图片标题6</a></li>31              <li><img src="http://www.mitxiong.com/NewsImages/2012101307276582.jpg" /><a href="#">图片标题7</a></li>32              <li><img src="http://www.mitxiong.com/NewsImages/2012082223432719.jpg" /><a href="#">图片标题8</a></li>33              <li><img src="http://www.mitxiong.com/NewsImages/2012082121509065.jpg" /><a href="#">图片标题9</a></li>34              <li><img src="http://www.mitxiong.com/NewsImages/2012081922387254.jpg" /><a href="#">图片标题10</a></li>35              <li><img src="http://www.mitxiong.com/NewsImages/2012081700252403.jpg" /><a href="#">图片标题11</a></li>36              <li><img src="http://www.mitxiong.com/NewsImages/2012081407597304.jpg" /><a href="#">图片标题12</a></li>37              <li><img src="http://www.mitxiong.com/NewsImages/2012081218248259.jpg" /><a href="#">图片标题13</a></li>38              <li><img src="http://www.mitxiong.com/NewsImages/2012080621278799.jpg" /><a href="#">图片标题14</a></li>39              <li><img src="http://www.mitxiong.com/NewsImages/2012072907484455.jpg" /><a href="#">图片标题15</a></li>40              <li><img src="http://www.mitxiong.com/NewsImages/2012072521564314.jpg" /><a href="#">图片标题16</a></li>41              <li><img src="http://www.mitxiong.com/NewsImages/2012072507238259.jpg" /><a href="#">图片标题17</a></li>42              <li><img src="http://www.mitxiong.com/NewsImages/2012072409035684.jpg" /><a href="#">图片标题18</a></li>43              <li><img src="http://www.mitxiong.com/NewsImages/2012072219405236.jpg" /><a href="#">图片标题19</a></li>44              <li><img src="http://www.mitxiong.com/NewsImages/2012071218416980.jpg" /><a href="#">图片标题20</a></li>45          </ul>46          <div id="loadimg" class="loadwrap"><img src="Images/load.jpg" /></div>47          <script type="text/javascript">48              function flow(mh, mv) {//参数mh和mv是定义数据块之间的间距,mh是水平距离,mv是垂直距离49                  var w = document.documentElement.offsetWidth;//计算页面宽度50                  var ul = document.getElementById("flow-box");51                  var li = ul.getElementsByTagName("li");52                  var iw = li[0].offsetWidth + mh;//计算数据块的宽度53                  var c = Math.floor(w / iw);//计算列数54                  ul.style.width = iw * c - mh + "px";//设置ul的宽度至适合便可以利用css定义的margin把所有内容居中55                  56                  var liLen = li.length;57                  var lenArr = [];58                  for (var i = 0; i < liLen; i++) {//遍历每一个数据块将高度记入数组59                      lenArr.push(li[i].offsetHeight);60                  }61                  62                  var oArr = [];63                  for (var i = 0; i < c; i++) {//把第一行排放好,并将每一列的高度记入数据oArr64                      li[i].style.top = "0";65                      li[i].style.left = iw * i + "px";66                      li[i].style.opacity = "1";67                      li[i].style["-moz-opacity"] = "1";68                      li[i].style["filter"] = "alpha(opacity=100)";69                      oArr.push(lenArr[i]);70                  }71                  72                  for (var i = c; i < liLen; i++) {//将其他数据块定位到最短的一列后面,然后再更新该列的高度73                      var x = _getMinKey(oArr);//获取最短的一列的索引值74                      li[i].style.top = oArr[x] + mv + "px";75                      li[i].style.left = iw * x + "px";76                      li[i].style.opacity = "1";77                      li[i].style["-moz-opacity"] = "1";78                      li[i].style["filter"] = "alpha(opacity=100)";79                      oArr[x] = lenArr[i] + oArr[x] + mv;//更新该列的高度80                  }81                 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//将loading移到下面82                 83                 function scroll() {//滚动加载数据84                     var st = oArr[_getMinKey(oArr)];85                     var scrollTop = document.documentElement.scrollTop > document.body.scrollTop? document.documentElement.scrollTop : document.body.scrollTop;86                     if (scrollTop >= st - document.documentElement.clientHeight) {87                         window.onscroll = null;//为防止重复执行,先清除事件88                         _request(null, "GetList.php", function(data) {//当滚动到达最短的一列的距离时便发送ajax请求新的数据,然后执行回调函数89                             _addItem(data.d, function() {//追加数据90                                 var liLenNew = li.length;91                                 for(var i = liLen; i < liLenNew; i++) {92                                     lenArr.push(li[i].offsetHeight);93                                 }94                                 for(var i = liLen; i < liLenNew; i++) {95                                     var x = _getMinKey(oArr);96                                     li[i].style.top = oArr[x] + 10 + "px";97                                     li[i].style.left = iw * x + "px";98                                     li[i].style.opacity = "1";99                                     li[i].style["-moz-opacity"] = "1";
100                                     li[i].style["filter"] = "alpha(opacity=100)";
101                                     oArr[x] = lenArr[i] + oArr[x] + 10;
102                                 }
103                                 document.getElementById("loadimg").style.top = _getMaxValue(oArr) + 50 + "px";//loading向下移位
104                                 liLen = liLenNew;
105                                 window.onscroll = scroll;//执行完成,恢愎onscroll事件
106                             });
107                         })
108                     }
109                 }
110                 window.onscroll =scroll;
111              }
112              //图片加载完成后执行
113              window.onload = function() {flow(10, 10)};
114              //改变窗口大小时重新布局
115               var re;
116               window.onresize = function() {
117                    clearTimeout(re);
118                    re = setTimeout(function() {flow(10, 10);}, 200);
119               }
120              //追加项
121              function _addItem(arr, callback) {
122                  var _html = "";
123                  var a = 0;
124                  var l = arr.length;
125                  (function loadimg() {
126                      

 

 

转载于:https://www.cnblogs.com/h-change/archive/2013/03/29/2989517.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.net web 开发平台- 表单设计器 一(web版)

如今为了适应需求的不断变化&#xff0c;动态表单设计器应运而生。它主要是为了满足界面的不断变化和提高开发速度。比如&#xff1a;一些页面客户可能也无法确定页面的终于布局&#xff0c;控件的位置&#xff0c;在哪种情况下显示或不显示等可能须要随时改动。为了应对这些需…

.NET程序配置文件操作(ini,cfg,config)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

MSP432P401R TI Drivers 库函数学习笔记(四)GPIO

目录API头文件函数 (机翻)宏GPIO驱动程序api返回的通用状态代码GPIO_PinConfig输出引脚配置宏GPIO_PinConfig输入引脚配置宏GPIO_PinConfig中断配置宏特殊的GPIO_PinConfig配置宏类型别名示例配置引脚示例配置外部中断示例上机实战配置引脚main.cmyTask.cmyTask.h实验结果平台&…

# Vue3 toRef 和 toRefs 函数

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

二分检索函数lower_bound()和upper_bound()

二分检索函数lower_bound()和upper_bound() 一、说明 头文件&#xff1a;<algorithm> 二分检索函数lower_bound()和upper_bound() lower_bound()&#xff1a;找到大于等于某值的第一次出现upper_bound()&#xff1a;找到大于某值的第一次出现必须从小到大排序后才能用 内…

MSP432P401R TI Drivers 库函数学习笔记(五)PWM

目录API (机翻)函数上机实战配置引脚PWM初始化&#xff0c;实现简易呼吸灯的效果实验结果完整代码myPWM.cmyPWM.hmyTask.cmyTask.hmain.cmain.h平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R SimpleLink™ 微控制器 LaunchPad™ 开发套件 (MSP-EXP432P401R) API …

防火墙配置十大任务之十,构建虚拟防火墙

防火墙配置任务十构建虚拟防火墙任务拓扑图10.11.inside区域的交换机的基本配置&#xff0c;在交换机上开启vlan2&#xff0c;vlan3&#xff0c;vlan4.三个vlan。图10.22.outside区域的Internet基本配置。图10.33.交换机上连接防火墙接口的配置。图10.44.inside区域各个PC的主机…

使用纯 CSS 实现超酷炫的粘性气泡效果

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

MSP432P401R TI Drivers 库函数学习笔记(六)UART 串口

目录API (机翻)上机实战配置初始化和实验实验结果整体代码myUart.cmyUart.hmyTask.cmyTask.hmain.cmain.h平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R SimpleLink™ 微控制器 LaunchPad™ 开发套件 (MSP-EXP432P401R) API (机翻) 官方UART API 手册 void UA…

Linux 批量杀死进程(详细版本)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

MSP432 库函数实现 PID 电机调角度、调速

目录引脚配置PWM引脚外部中断测量编码器引脚配置代码部分初始化编码器解读Encoder.cEncoder.h测速和控制部分卡尔曼滤波器&#xff0c;用于对所测速度进行滤波kalman.ckalman.h实验效果速度滤波效果控速效果控角效果平台&#xff1a;Code Composer Studio 10.4.0 MSP432P401R …

20.网页卷去的距离与偏移量

我们先来看看下面的图&#xff1a; scrollLeft:设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离 &#xff0c;即左边灰色的内容。 scrollTop:设置或获取位于对象最顶端与窗口中可见内容的最顶端之间的距离 &#xff0c;即上边灰色的内容。 offsetLeft:获取…

【电赛】一阶卡尔曼滤波器 滤波效果良好

目录代码kalman.ckalman.h滤波效果很久以前抄的&#xff0c;忘了是从哪弄的了 我把它改成了这种结构体指针传参的形式&#xff0c;方便在比赛中应用。应用举例见MSP432 PID 电机调角度、调速。 它曾助力笔者获2020年电赛省一等奖。 代码 Q:过程噪声协方差 Q参数调滤波后的曲线…

计算机是如何启动的?

从打开电源到开始操作&#xff0c;计算机的启动是一个非常复杂的过程。 我一直搞不清楚&#xff0c;这个过程到底是怎么回事&#xff0c;只看见屏幕快速滚动各种提示......这几天&#xff0c;我查了一些资料&#xff0c;试图搞懂它。下面就是我整理的笔记。 零、boot的含义 先问…

hdu 1536(博弈)

传送门&#xff1a;S-Nim 题意&#xff1a;给n个数的集合s&#xff0c; 再给m 组数据&#xff0c;每组表示 k 堆石子&#xff0c;每次可以取的个数只能是集合s中的数量。问先手胜还是输&#xff1f; 分析&#xff1a;sg函数的经典运用&#xff0c;先预处理出所有数量为0~10000的…

写了个 Markdown 命令行小工具,希望能提高园友们发文的效率!

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

MSP432P401R TI Drivers 库函数学习笔记(七)I2C驱动OLED屏幕

目录API (机翻)上机实战引脚配置I2C引脚配置工作指示灯LED1引脚配置文件结构I2C 初始化、读写函数myI2C.cmyI2C.hOLED初始化和测试代码main.cmain.hOLED 驱动程序OLED.cOLED.hOLED_Font.h任务管理myTask.cmyTask.h显示效果平台&#xff1a;Code Composer Studio 10.4.0 MSP432…

在WPF中实现玻璃模糊效果

在WPF中实现玻璃模糊效果还是比较简单的&#xff0c;主要方式如下&#xff1a; 添加一个Rectangle或其它控件作为玻璃放到顶部图层 将底部图像作为Brush&#xff08;大多数的时候用VisualBrush&#xff09;填充到Rectangle中 对该Rectangle添加高斯模糊效果 在该Rectangle上叠加…

MSP432P401R TI Drivers 库函数学习笔记(八)ADC

目录API (机翻)上机实战引脚配置ADC引脚配置串口引脚配置指示工作状态的LED1引脚配置代码部分ADC初始化和读取函数myADC.cmyADC.h获取数据并通过串口发送main.cmain.h任务管理函数myTask.cmyTask.h串口代码myUart.cmyUart.h实验结果平台&#xff1a;Code Composer Studio 10.4.…

PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据

介绍承接上文的PHP 杂谈《重构-改善既有代码的设计》之 重新组织你的函数继续重构方面的内容。这章主要针对数据的重构。1、争论的声音——直接访问Field还是通过函数&#xff08;Accessor&#xff09;访问Field2.修改Array为Object&#xff1a;当你看到一个Array很像一个数据结…