<ul id="ul1"><li> <div><img src="images/1.jpg"><p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div></li><li> <div><img src="images/2.jpg"><p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div></li><li> <div><img src="images/3.jpg"><p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div></li><li> <div><img src="images/4.jpg"><p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div></li> </ul>css
*{ margin:0; padding: 0;}ul li{ list-style: none;}#ul1{ width: 1080px; margin: 100px auto 0;}li{ width: 247px; float: left; margin-right: 10px;}li div{ border:1px solid #000;padding:10px; margin-bottom:10px;}li div img{ width: 225px;display: block;}基本效果如图:
样式显示没问题之后,就把li里面的代码删掉。
接下来通过ajax来动态添加。
数据哪里来?
这里用的是wookmark的数据接口。
http://www.wookmark.com/api/json/popular?page=1
点开url得到是一个json。
信息量很大。怎么分析?
一般可以看文档。但是手头没有文档的情况下,可以看看链接。返回是什么鬼。
function createUrl(num){ return "http://www.wookmark.com/api/json/popular?page="+num+"&callback=?";}$(function(){ $.getJSON(createUrl(1),function(data){console.log(data); })})控制台打印结果为:
原来是一个50个图片信息组成的数组。每个数组元素都是一个json。在这个简单的demo里面,暂时只需要取preview属性和title属性就好了。
布局实现
关键之一在于,判断最短的li,事实上我们需要最短高度li的索引值。
//找出高度最小li的索引值function getShortestLi(){ var shortest=0; for(var i=1;i<4;i++){if($("li").eq(i).height()<$("li").eq(shortest).height()){ shortest=i;} } return shortest;}然后就是getJSON方法
$(function(){ $.getJSON(createUrl(1),function(data){//console.log(data);for(var i=0;i<dataArr.length;i++){ var $html=$("<div><img src=""+data[i].preview+""><p>"+data[i].title+"</p></div>"); //console.log($("li").eq(getShortestLi()).height()) $("li").eq(getShortestLi()).append($html);};console.log([$("li").eq(0).height(),$("li").eq(1).height(),$("li").eq(2).height(),$("li").eq(3).height()]) })})再加载看看,布局就出来了。简单又漂亮。
做到这里,看起来一切都挺好。然而潜伏着一个致命的问题。
for循环惹的祸?
看看console.log的信息。为了分析,我把4个li的高度放进了一个数组:
50张图片分4列,少说平均高度也得有三四千像素。
而到循环结束,程序判断的终点竟然只有令人发指的1000多个px,因为图片加载过程慢于for循环执行速度。虽然demo里的显示还算正常,但这种代码在网速不好时,会造成工作事故。
思路一:可以判断图片是否加载完成。
可以用个定时器监听下,然后用递归实现,我的方案是这样
var index=0; function LoadPic(index){var $html=$("<div><img src=""+data[index].preview+""><p>"+data[index].title+"</p></div>")$("li").eq(getShortestLi()).append($html);var oImg=$html.find("img");var t=setInterval(function(){ if(oImg.height()!=0){//如果加载完了。clearInterval(t);//console.log([$("li").eq(0).height(),$("li").eq(1).height(),$("li").eq(2).height(),$("li").eq(3).height()])if(index<50){ return LoadPic(index+1);}else{ return false;}}else{console.log("wait") }},50)//每隔50ms监听一次 } LoadPic(0);但是,从用户体验的角度来说,等一张图加载完成再进行下一张加载是不友好的。数据提供方都应该直接把图片的高度在服务器处理好,json数据里面返回过来。网速很慢的时候,要等好久,然后一下子图片都出来了,不觉得很诡异吗?尤其是第三方接口。一加载不出来就出大问题了。
$(function(){ $.getJSON(createUrl(1),function(data){console.log(data);for(var i=0;i<data.length;i++){//console.log(data[i].preview);var $html=$("<div><img src=""+data[i].preview+""><p>"+data[i].title+"</p></div>")$("li").eq(getShortestLi()).append($html);$html.find("img").css("height",(data[i].height*225/data[i].width)+"px");$html.find("img").css("width","225px");};//console.log([$("li").eq(0).height(),$("li").eq(1).height(),$("li").eq(2).height(),$("li").eq(3).height()]) })})事实上个人认为这是最简单且用户体验最好的方案。
换句话说,最短li的高度与该li到页面顶部之和小于滚动条高度和可视区高度之和时,触发li加载。
li的高度好求。但是最短li到页面顶部距离怎么求?
原生的方法可以这样实现:
function getTop(obj){ var iTop=0; while(obj){iTop+=obj.offsetTop;obj=obj.offsetParent; }//累加元素本身和自身所有父级高度偏移值 return iTop;}但是本案例既然是用jquery,自然有它的方法。
obj.offset().top
window.onscroll=function(){...}
$(window).scroll(function(){...})
(window).scroll(function(){var $li=$("li").eq(getShortestLi());var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//console.log([$li.offset().top+$li.height(),document.documentElement.clientHeight+scrollTop])//如果li高度与li到页面顶部的高度之和<可视区高度+滚动距离if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){alert(1);} })运行代码,发现第一个到底的li出现是可视区时,弹出1.证明可用。
//找出高度最小li的索引值function getShortestLi(){ var shortest=0; for(var i=1;i<4;i++){if($("li").eq(i).height()<$("li").eq(shortest).height()){ shortest=i;} } return shortest;}function createUrl(num){ return "http://www.wookmark.com/api/json/popular?page="+num+"&callback=?";}function getList(n){ $.getJSON(createUrl(n),function(data){//console.log(data);for(var i=0;i<data.length;i++){ var $html=var $html=$("<div><img src=""+data[i].preview+""><p>"+data[i].title+"</p></div>"); //console.log(data[i].height); $("li").eq(getShortestLi()).append($html); dataArr[i].height*=225/dataArr[i].width; $html.find("img").css("height",dataArr[i].height+"px"); $html.find("img").css("width","225px");};}$(function(){ var pageNum=1; getList(pageNum); $(window).scroll(function(){var $li=$("li").eq(getShortestLi();var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){ pageNum++; console.log(pageNum); getList(pageNum);} })})这样一来,好像可以实现了。但是一看控制台的console.log,又发现问题。
//找出高度最小li的索引值function getShortestLi(){ var shortest=0; for(var i=1;i<4;i++){if($("li").eq(i).height()<$("li").eq(shortest).height()){ shortest=i;} } return shortest;}function createUrl(num){ return "http://www.wookmark.com/api/json/popular?page="+num+"&callback=?";}var bCheck=false;function getList(n){ $.getJSON(createUrl(n),function(data){if(data.length==0){ return false;}else{ for(var i=0;i<data.length;i++){ //console.log(data[i].preview);var $html=$("<div><img src=""+data[i].preview+""><p>"+data[i].title+"</p></div>");$("li").eq(getShortestLi()).append($html);$html.find("img").css("height",(data[i].height*225/data[i].width)+"px");$html.find("img").css("width","225px");};}bCheck=true;});}$(function(){ var pageNum=1; getList(pageNum); $(window).scroll(function(){var $li=$("li").eq(getShortestLi());var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//console.log([$li.offset().top+$li.height(),document.documentElement.clientHeight+scrollTop])//如果li高度与li到页面顶部的高度之和<可视区高度+滚动距离if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){ if(bCheck){bCheck=false;pageNum++;//console.log(pageNum);getList(pageNum);}else{return false; } } })})以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!