jquery实现简单的瀑布流布局

是开头都会说的原理

瀑布流布局有两种,一种是固定列,一种是非固定列。在此主要记述第一种的实现。

固定列的特征是:无论页面如何缩放,每行的总列数都一致。

一行4列的瀑布流从布局的角度来说,就是4个li标签。通过一定的事件(比如滚动条滚动多少px),然后读取之,再把数据动态地添加到页面中。

添加数据原则,不是根据li索引值来加,而是根据各列中高度最短的的那列动态添加。否则可能导致页面很难看(左右高度不统一)。

实例涉及ajax方法。可在服务器环境下运行。

废话不多说了。直接上样式。

 <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数据里面返回过来。网速很慢的时候,要等好久,然后一下子图片都出来了,不觉得很诡异吗?尤其是第三方接口。一加载不出来就出大问题了。

所幸的是,第三方提供了图片的宽高信息。

因此for循环还是可以有的,在返回的数据里面,有宽度和高度值。利用它们就可以实现定宽(255px)和定高(原始高度乘上一个比例)。

$(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的高度好求。但是最短li到页面顶部距离怎么求?

原生的方法可以这样实现:

function getTop(obj){
 var iTop=0;
 while(obj){
 iTop+=obj.offsetTop;
 obj=obj.offsetParent;
 }//累加元素本身和自身所有父级高度偏移值
 return iTop;
}

但是本案例既然是用jquery,自然有它的方法。

obj.offset().top

滚动事件

原生的实现方法是:window.onscroll=function(){...}

jquery的实现方法是:$(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.证明可用。

因为涉及到滚动事件,所以getJSON相关函数应该封装为getList()方便调用。所以需要重新调整一下。

此时的代码是这样的:

//找出高度最小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,又发现问题。

如厕的逻辑

在触发加载前提时,图片正在加载,期间动了滚动条,就又触发第二次加载,再动一下,就触发第三次,于是短短一瞬间,触发了n次加载。

那就做一个开关吧。

就跟公厕逻辑一样。n个人排队进一个坑位。外面的人想要进去首先得判断门是否锁上了。没锁才能进。进去之后第一件事把门锁上。等如厕完毕,门就打开。后面的人才能进

新设置一个开关bCheck,默认为true。

到触发加载条件时,还要判断bCheck是否为真(门开),为真时才能触发getList()(如厕)。否则return false(只能等)。

getList一开始就把bCheck设为false(如厕前先锁门)。等到getList回调函数执行到尾声。再把bCheck设为true(开门)。

这一段不贴代码了。

总有流完的一天。

当数据结束时(所有人上完厕所),就没有必要再进行加载了(自动把门锁上)。

所以在getJSON回调函数内锁门之后发现进来的是个空数组,那就进行判断,当获取到data的length为空时,直接returnfalse。那么bCheck就永远关上了。

全部代码如下:

//找出高度最小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;
  }
 }
 })
})

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • Jquery实现瀑布流布局(备有详细注释)

    本文实例讲述了Jquery实现瀑布流布局的方法.分享给大家供大家参考.具体如下: 瀑布流布局最近真的很流行,很多人都跟我一样想知道是怎么做出来的吧,经过网上搜索大量的参考结合N边的实验今天终于被我写出来了,为了便于大家理解我使用了jQuery(当然用源生js代码执行的效率会高一些,但是很多人多源生js不是很熟练). <!doctype html> <html> <head> <meta charset="utf-8"> <title

  • 网页瀑布流布局jQuery实现代码

    什么是瀑布流网页布局? 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部. 下面来看代码,用纯CSS3来做看效果怎样! HTML <div id="all"> <div class="box"> <div class="pic"> <img src="cars/1.jpg"/>

  • jQuery 瀑布流 绝对定位布局(二)(延迟AJAX加载图片)

    瀑布流-绝对定位布局,与浮动布局的区别在于 1.布局不一样: 绝对定位:一个UL里面放置所有的绝对定位的LI: 浮动布局:多个(一般三四个)UL分布放置LI: 2.AJAX不一样 绝对定位:只需要将请求来的JSON数据(当然可以是别的格式的数据),插入到UL就可以了.然后再对这个新插入的LI进行TOP和LEFT设置: 浮动布置:是将请求来的JSON数据(当然可以是别的格式的数据),分别插入到对应的UL当中,因为有绝对定位,所以不用对LI设置位置.会自动向下排列: 一.功能分析: 1.定位每一个L

  • jQuery+HTML5美女瀑布流布局实现方法

    本文实例讲述了jQuery+HTML5美女瀑布流布局实现方法.分享给大家供大家参考.具体如下: 这是一款JavaScript与HTML5实现美女瀑布流布局,本方法是把图片的路径写在了JS的数组里,不过重点好像不是在这里,而是在图片如何自动排列的问题,你可以运行本实例后,点击"加载瀑布流布局"按钮,即可看到图片的瀑布流排列效果,现在很流行这个,希望您从本代码中能找到一些灵感. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-html

  • 基于jquery实现瀑布流布局

    本文实例为大家介绍了基于jquery实现瀑布流布局的关键代码,分享给大家供大家参考,具体内容如下 效果图: 具体代码: 使用jquery-1.8.3.min.js,waterfall.js代码如下: $( window ).load( function(e){ waterfall(); var dataInt = { 'data': [{ 'src': '1.jpg' },{ 'src': '2.jpg' },{ 'src': '3.jpg' },{ 'src': '4.jpg' }]}; $(

  • jQuery 瀑布流 浮动布局(一)(延迟AJAX加载图片)

    浮动布局:即HTML结构的列,是用浮动方式. 一.功能分析: 1.判断图片是否进入可视区域: 2.用AJAX请求服务器数据: 3.将数据播入到相应的列队: 二.实现方法: 给window的scroll事件l绑定一个处理函数:做如下工作: 1.如何判断最后一行的图片,是否进入了可视区域? 如果:最后一行的某个图片距离浏览器可视区域顶部的距离值 小于 (可视区域的高度+滚动条滑动的距离值): 那么:就可以判定这个图片进入了浏览器的可视区域: 2.如何用AJAX请求服务器数据; $.getJSON()

  • jQuery实现瀑布流布局

    HTML 复制代码 代码如下: <div id="main">          <div class="box">              <div class="pic">                  <img src="images/0.jpg" alt="">              </div>          </di

  • jquery实现超简单的瀑布流布局【推荐】

    1.看看效果吧! 2.html代码index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> ul{position: relative;padding: 0 -3px;list-style: none;width: 600px;margi

  • jQuery实现瀑布流布局详解(PC和移动端)

    瀑布流布局已成为当今非常普遍的图片展示方式,无论是PC还是手机等移动设备上.这种布局图片的样式大概分为三种:等高等宽.等宽不等高.等高不等宽,接下来我们就最为普遍的等宽不等高形式来作为示例. 我们用百度图片作为范例: 这就是PC端比较常见的瀑布流布局方式,接下来我们审查下元素看看百度图片里面是如何布局: 可以看到,它里面实际是若干个等宽的列容器,通过计算将图片push到不同的容器里.而本文介绍的展示方法是通过定位的方式,虽然最后布局展示的方式不同,但之前的算法都比较类似. 动手 首先我们将如下样

  • jquery实现简单的瀑布流布局

    是开头都会说的原理 瀑布流布局有两种,一种是固定列,一种是非固定列.在此主要记述第一种的实现. 固定列的特征是:无论页面如何缩放,每行的总列数都一致. 一行4列的瀑布流从布局的角度来说,就是4个li标签.通过一定的事件(比如滚动条滚动多少px),然后读取之,再把数据动态地添加到页面中. 添加数据原则,不是根据li索引值来加,而是根据各列中高度最短的的那列动态添加.否则可能导致页面很难看(左右高度不统一). 实例涉及ajax方法.可在服务器环境下运行. 废话不多说了.直接上样式. <ul id=&qu

  • vue实现简单瀑布流布局

    vue简单实现瀑布流布局的一种方式(vue瀑布流组件),供大家参考,具体内容如下 vue中的瀑布流布局组件 需求:图片容器宽度固定,高度根据图片自适应,图片一行不能排列时候,换行依次从左往右排列.(瀑布流概念) 另外结合vue-lazy实现懒加载 ( npm i vue-lazyload --save-dev) 使用也很简单,在需要懒加载的img标签上将:src换成v-lazy 父组件传递数据: waterfallData:[ { e_img: "test.jpg", // 图片 e_

  • 微信小程序实现瀑布流布局与无限加载的方法详解

    前言 瀑布流布局是一种比较流行的页面布局方式,最典型的就是Pinterest.com,每个卡片的高度不都一样,形成一种参差不齐的美感. 在HTML5中,我们可以找到很多基于jQuery之类实现的瀑布流布局插件,轻松做出这样的布局形式.在微信小程序中,我们也可以做出这样的效果,不过由于小程序框架的一些特性,在实现思路上还是有一些差别的. 今天我们就来看一下如何在小程序中去实现这种瀑布流布局: 小程序瀑布流布局 我们要实现的是一个固定2列的布局,然后将图片数据动态加载进这两列中(而加载进来的图片,会

  • 三种方式实现瀑布流布局

    分别使用javascript,jquery,css实现瀑布流布局: 第一种方式:使用JavaScript: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>瀑布流布局</title> <style> *{padding:0;margin:0;} .clearfix:after, .clearf

  • JQuery实现简单瀑布流布局

    本文实例为大家分享了JQuery实现简单瀑布流布局的具体代码,供大家参考,具体内容如下 分享一个基于JQuery实现的瀑布流布局,效果如下: 实现代码如下,欢迎大家复制粘贴. <!DOCTYPE html> <html>   <head>     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />     <title>

随机推荐