服务器代理+jQuery.ajax实现图片瀑布流
- 服务器代理机制破解浏览器的同源策略
- 瀑布流功能实现分析
- 具体实现代码及业务实现分析
一、服务器代理机制破解浏览器同源策略
由于浏览器的同源策略无法请求不同域名下的资源,但是服务器的后台程序并不受同源策略的限制,所以就可以通过服务器的后台程序获取其他域名下的资源,然后再发送给浏览器,本质上还是在同源策略下实现的,毕竟服务器没有跨域这一说法,这种机制叫做服务器代理。(这篇博客不是为了解析服务器代理,所以不对服务器代理的实现做什么分析,只简单的描述浏览器在同源基础上获取其他域名下的资源)。
二、瀑布流功能实现分析
1.初始加载页面时获取一次服务器资源,将获取的资源根据每列的高度以最小原则添加图片。
2.当滚动条下滑时,出现空白区域时,即滚动条滚动的位置加上视窗的高度大于最小高度列的高度。触发加载资源,再添加图片。
需要的数据:
视窗高度:window.innerHeight(原生BOM属性);$(window).height();(jQuery方法)。
滚动条的位置:
谷歌浏览器和未声明DTD <! DOCTYPE>获取滚动条的位置:document.body.scrollTop;
火狐和其他浏览器:document.bodyElement.scrollTop;
IE9+ 和 最新浏览器都支持:window.pageXOffset; pageYOffset(scrollTop);
兼容: var scrollTop = window.pageYOffset ||document.documentElement.scrollTop || document.body.scrollTop || 0;
jQuery:$(window).scrollTop();
三、具体实现代码及业务实现分析
web层:这里我使用了百度的资源,data数据能获取,但是由于百度图片有保护措施,最后获取的都是一张替代图片,但是不影响我们实现瀑布流功能。下面是实现服务器代理机制的PHP内容:(rn是一次请求数据的个数,可自己根据需求设置,其他数据大家自己去查吧,方正都没啥用,因为图片都是那张替代图片,但是连接是真实的)
<?php header('Content-type:text/html; charset="utf-8"'); $url = 'http://image.baidu.com/data/imgs?col=美女&tag=小清新&sort=10&pn=1&rn=20&p=channel&from=1'; $content = file_get_contents($url); echo $content; ?>
通讯层:
1 function getData(){ 2 if(!flag){ 3 flag = true; 4 $.ajax({ 5 type:'GET', 6 url:'http://localhost/jy_11_12_13/11_1/src/getPics.php?', 7 success:addDom, 8 beforeSend:function(){ 9 $('.loading').show();//请求成功前显示loading 10 }, 11 error:function(){ 12 console.log('error'); 13 } 14 }); 15 } 16 }
根据数据-插入结构:
1 function addDom(data){ 2 $('.loading').hide();//请求成功后隐藏loading 3 // var oJSON = (new Function('return ' + data))();//标准JSON数据格式解释方法 4 var oJSON = eval("(" + data + ")");//数据不是标准JSON格式,只能采用eval来解析 5 var dataList = oJSON.imgs; 6 dataList.pop();//清除最后一个空数据 7 console.log(dataList);//在控制台打印数据,查看数据是否跟需求一致 8 if(dataList.length > 0){ 9 //拿到数据后,遍历数据插入结构 10 dataList.forEach(function(ele,index){ 11 var iDiv = $('<div class="item"></div>'); 12 var imgBox = $('<div class="image"></div>'); 13 var oImg = new Image(); 14 var oP = $('<p></p>'); 15 oP.text(ele.title); 16 oImg.src = ele.imageUrl; 17 //当图片获取到了以后插入页面 18 oImg.onload = function(){ 19 imgBox.append(oImg); 20 iDiv.append(imgBox).append(oP); 21 //获取最短的li的索引 22 var index = getMinList(oLi); 23 $(oLi[index]).append(iDiv); 24 } 25 }); 26 } 27 num ++;//这个数据是用来记录页的,之前的一个数据可以实现分页请求, 28 flag = false;//结构添加完成后将锁开启 29 }
滚动操作:
1 //获取最短li的索引函数 2 function getMinList(dom){ 3 var minHeight = parseInt($(dom[0]).css('height')); 4 var index = 0; 5 for(var i = 1; i < oLi.length; i++){ 6 var height = parseInt($(dom[i]).css('height')); 7 if(height < minHeight){ 8 minHeight = height; 9 index = i; 10 } 11 } 12 return index; 13 } 14 //往下滑动时 15 //当滚动条的位置加上窗口高度大于最短的li,再次加载 16 $(window).scroll(function() { 17 var scrollHeight = $(window).scrollTop();//获取滚动条位置 18 var clientHeight = $(window).height();//获取视窗高度 19 var minLiH = parseInt($(oLi[getMinList(oLi)]).css('height'));//获取最短列的高度 20 if(scrollHeight + clientHeight > minLiH){//当出现空白区域时调用网络请求加载数据 21 getData(); 22 } 23 });
最后全部代码(折叠);
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <title>jQuery瀑布流(服务器代理)</title> 7 <link rel="stylesheet" href="./css/index.css"> 8 </head> 9 <body> 10 <div class="wrapper"> 11 <ul> 12 <li> 13 <div class="item"> 14 <div class="image"> 15 <img src="./image/0.png" alt=""> 16 <p>我是title</p> 17 </div> 18 </div> 19 </li> 20 <li> 21 <div class="item"> 22 <div class="image"> 23 <img src="./image/1.png" alt=""> 24 <p>我是title</p> 25 </div> 26 </div> 27 </li> 28 <li> 29 <div class="item"> 30 <div class="image"> 31 <img src="./image/2.png" alt=""> 32 <p>我是title</p> 33 </div> 34 </div> 35 </li> 36 <li> 37 <div class="item"> 38 <div class="image"> 39 <img src="./image/3.png" alt=""> 40 <p>我是title</p> 41 </div> 42 </div> 43 </li> 44 </ul> 45 <div class="loading">Loading...</div> 46 </div> 47 <script type="text/javascript" src="./js/jquery-2.0.3.js"></script> 48 <script type="text/javascript" src="./js/index.js"></script> 49 </body> 50 </html>
1 *{ 2 margin: 0; 3 padding: 0; 4 list-style: none; 5 } 6 .wrapper{ 7 /* 最小宽度 */ 8 min-width: 930px; 9 margin: 0 auto; 10 text-align: center; 11 } 12 .wrapper ul{ 13 display: inline-block; 14 } 15 .wrapper ul::after{ 16 content: ""; 17 clear: both; 18 display: block; 19 } 20 .wrapper li{ 21 float: left; 22 } 23 .wrapper li .item{ 24 width: 200px; 25 margin: 0 5px 10px; 26 padding: 10px; 27 border: 1px solid #ccc; 28 } 29 .wrapper li .item .image{ 30 width: 200px; 31 } 32 .wrapper li .item .image img{ 33 width: 200px; 34 } 35 .wrapper .loading{ 36 font-size: 30px; 37 font-weight: bolder; 38 color: #ccc; 39 }
1 var num = 1; 2 var flag = false;//加锁 3 var oLi = $('li'); 4 getData(); 5 function getData(){ 6 if(!flag){ 7 flag = true; 8 $.ajax({ 9 type:'GET', 10 url:'http://localhost/jy_11_12_13/11_1/src/getPics.php?', 11 success:addDom, 12 beforeSend:function(){ 13 $('.loading').show();//请求成功前显示loading 14 }, 15 error:function(){ 16 console.log('error'); 17 } 18 }); 19 } 20 } 21 function addDom(data){ 22 $('.loading').hide();//请求成功后隐藏loading 23 // var oJSON = (new Function('return ' + data))();//标准JSON数据格式解释方法 24 var oJSON = eval("(" + data + ")");//数据不是标准JSON格式,只能采用eval来解析 25 var dataList = oJSON.imgs; 26 dataList.pop();//清除最后一个空数据 27 console.log(dataList);//在控制台打印数据,查看数据是否跟需求一致 28 if(dataList.length > 0){ 29 //拿到数据后,遍历数据插入结构 30 dataList.forEach(function(ele,index){ 31 var iDiv = $('<div class="item"></div>'); 32 var imgBox = $('<div class="image"></div>'); 33 var oImg = new Image(); 34 var oP = $('<p></p>'); 35 oP.text(ele.title); 36 oImg.src = ele.imageUrl; 37 //当图片获取到了以后插入页面 38 oImg.onload = function(){ 39 imgBox.append(oImg); 40 iDiv.append(imgBox).append(oP); 41 //获取最短的li的索引 42 var index = getMinList(oLi); 43 $(oLi[index]).append(iDiv); 44 } 45 }); 46 } 47 num ++;//这个数据是用来记录页的,之前的一个数据可以实现分页请求, 48 flag = false;//结构添加完成后将锁开启 49 } 50 //获取最短li的索引函数 51 function getMinList(dom){ 52 var minHeight = parseInt($(dom[0]).css('height')); 53 var index = 0; 54 for(var i = 1; i < oLi.length; i++){ 55 var height = parseInt($(dom[i]).css('height')); 56 if(height < minHeight){ 57 minHeight = height; 58 index = i; 59 } 60 } 61 return index; 62 } 63 //往下滑动时 64 //当滚动条的位置加上窗口高度大于最短的li,再次加载 65 $(window).scroll(function() { 66 var scrollHeight = $(window).scrollTop();//获取滚动条位置 67 var clientHeight = $(window).height();//获取视窗高度 68 var minLiH = parseInt($(oLi[getMinList(oLi)]).css('height'));//获取最短列的高度 69 if(scrollHeight + clientHeight > minLiH){//当出现空白区域时调用网络请求加载数据 70 getData(); 71 } 72 });