项目里面要实现这么一个效果,类似腾讯QQ空间那种利用滚动条来翻页,但是还要有数字分页再带一个类似时间轴的东西显示在右边。于是 Google it!网上有很多代码,但我发觉没一个可以用,包括JQUERY官方提供的的插件都那么不尽人意,于是自己动手写一个。
1、首先要实现的第一个效果就是滚动翻页,和数字翻页如图(数据都是通过ajax往后台请求)
2、实现一个时间轴,主要为了良好的用户体验(其实用处不大,主要在时间轴上加上锚点),如图
3、数字分页和滚动翻页的结合:比如用户一进到页面,没有滚动那么自然只有第一页(1-10条记录)的数据。每次将滚动条、滚动到下面的时候就去后台请求下一页的数据,这个JS操作网上一大把,但是都不行。原因是发多次请求,加载出来重复的数据。这个问题解决方法就是每次需要往后台加载数据的时候先window的scroll的监听事件取消,然后执行ajax请求,执行完ajax后根据返回出来的信息判断时候还需要添加window的scroll监听事件,比如当数据已经全部加载完了则不需要为window再次添加scroll,否则再一次为window添加scroll。代码如下:
根据ajax返回来的信息判断是否要为window再次加上scroll的监听事件
至此滚动翻页的功能就完成了,基本和腾讯QQ空间的那个无线下拉翻页没什么区别。但是我们项目里面还要加上一个数字分页,这个功能本身没什么难点,难的是要和滚动翻页结合,比方用户首先进来不滚动翻页,直接点击一个数字翻页假设他点击的是3,那么我首先得判断第三页(20-30条记录)的数据是否被加载出来了,是否显示在页面上了,如果已经加载出来显示在页面上了那么就利用HTML的锚点跳转功能,使浏览器定位到第(20条记录),如果没有加载出来,在发送ajax请求往后台请求数据加载并显示。
用户第一次进到页面:
当用户直接点击数字翻页钟的3:
如果这个时候用户在此点击数字翻页钟的2的时候数据情况:
数据展示:
如果用户这个时候又去滚动 滚动条,那么就会往后台请求数据(由于第三页和第2页的数据已经被加载请出来了),所以直接往后台加载第4页的数据————这个功能也是最难实现的,也是最能体现用户体验的地方
直接上图: 使用滚动条滚动的时候
服务器端的java代码:
@Override @RequestMapping(value="designer.xhtml") /* * <p>Title: forward</p> * <p>Description:查询设计师 </p> * @param model * @param request * @param response * @return * @see com.kecg.web.base.BaseController#forward(org.springframework.ui.ModelMap, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ public String forward(ModelMap model, HttpServletRequest request, HttpServletResponse response) { try { MemberEntity mentity = (MemberEntity) this.conditionParam(request, null, MemberEntity.class); mentity.setRecommendFlag(1); PageResult pr = memberService.query4List(request, mentity, 1); request.setAttribute("list",pr.getList()); request.setAttribute("page",pr.getPageUtil()); request.setAttribute("total",pr.getTotal()); } catch (Exception e) { e.printStackTrace(); } return "model/modelDesigner"; } @RequestMapping(value="ajaxLoadDesigner.xhtml") public @ResponseBody Map<String,Object> ajaxLoadDesigner(HttpServletRequest request, HttpServletResponse response){ Map<String,Object> map = new HashMap<String,Object>(); try { MemberEntity mentity = (MemberEntity) this.conditionParam(request, null, MemberEntity.class); mentity.setRecommendFlag(1); PageResult pr = memberService.query4List(request, mentity, 1); map.put("list",pr.getList()); map.put("page",pr.getPageUtil()); map.put("total",pr.getTotal()); return map; } catch (Exception e) { e.printStackTrace(); } return map; }
JS代码:
var currentPage =2; var tatalPage = ""; var scrollFlag="1"; var hght=0;//初始化滚动条总长 var top=0;//初始化滚动条的当前位置 $(function() { /* 点击更多 加载更多 */ $("#sea_more").click( function(){ var brand = document.getElementById("sea_padding1"); brand.style.display=="block"?brand.style.display="none":brand.style.display="block"; }); $(".addClass").qtip({ position : { my : 'bottom right', at : 'top center' }, style : { classes : 'ui-tooltip-dark ui-tooltip-shadow ui-tooltip-rounded' } }); //滚动翻页 $(window).bind("scroll",scrollFun); var top = $('#timeline').offset().top - parseFloat($('#timeline').css('marginTop').replace(/auto/, 0)); var topage = $('#designerPage').offset().top - parseFloat($('#designerPage').css('marginTop').replace(/auto/, 0)); var footTop = $('#dis_footer').offset().top - parseFloat($('#dis_footer').css('marginTop').replace(/auto/, 0)); var maxY = footTop - $('#timeline').outerHeight(); var maxYP = footTop - $('#designerPage').outerHeight(); $(window).scroll(function(evt) { var y = $(this).scrollTop(); if (y > top) { if (y < maxY) { $('#timeline').addClass('fixed').removeAttr('style'); } else { $('#timeline').removeClass('fixed').css({ position: 'absolute', top: (maxY - top) + 'px' }); } } else { $('#timeline').removeClass('fixed'); } if(y>topage){ if (y < maxYP) { $('#designerPage').addClass('fixed').removeAttr('style'); } else { $('#designerPage').removeClass('fixed').css({ position: 'absolute', top: (maxYP - top) + 'px' }); } }else{ $('#designerPage').removeClass('fixed'); } }); }); function hrefCurrentPage(obj){ $('html,body').animate({scrollTop:$('#'+obj).offset().top}, 800); } function pageFun(obj,obj1){ var info = $('#'+obj).attr('class'); if(info){ $('html,body').animate({scrollTop:$('#'+obj).offset().top}, 800); }else{ $(window).unbind(); currentPage = obj1; ajaxLoadData() setTimeout('hrefCurrentPage(\"'+obj+'\")',1000); return; } } function scrollFun(){ $(window).scrollTop();//这个方法是当前滚动条滚动的距离 $(window).height();//获取当前窗体的高度 $(document).height();//获取当前文档的高度 var bot = 10; //bot是底部距离的高度 if ((bot + $(window).scrollTop()) >= ($(document).height() - $(window).height())) { //当底部基本距离+滚动的高度〉=文档的高度-窗体的高度时; //我们需要去异步加载数据,每次执行ajax之前先取消window的scroll事件监听(防止多次请求数据) $(window).unbind(); existLoad(currentPage);//判断当前页码的数据是否已经被加载,如果没有则往后台请求加载数据 return; } }; function existLoad(obj){ var clazz = $('#'+obj+'0box').attr('class'); console.log(clazz); if(clazz){//当前这个页码的数据已经存在 currentPage++; existLoad(currentPage); }else{ setTimeout('ajaxLoadData()',1000); return; } return false; } function ajaxLoadData(){ $.ajax({type: 'POST', url: 'ajaxLoadDesigner.xhtml', data: {"currentPage":currentPage}, success: function(data){ if(currentPage>=data.page.totalPage){//如果当前页大于等于总页则表示数据全部加载完毕 currentPage = data.page.totalPage; $(window).unbind();//取消window的scroll事件监听(再怎么滚动都不会去后台加载数据了) $(".desigenerLoadingMore").html("已经全部加载完毕"); }else{//如果数据还没有全部加载完毕,设置当前页为服务器端返回的当前页 currentPage=data.page.currentPage; //并且再次为window加上scroll的监听事件 //(由于之前在ajax请求之前已经取消了对scroll的监听,故而这里需要手动再一次加上) $(window).bind("scroll",scrollFun); } ajaxLoadDesignerCall(data); }, dataType: 'json' }); } function checkedDesigner(obj){ var html= '<div class="seleceedLabel"><p class="selectedLeft"></p>'+ '<p class="selectedText">'+obj+'</p><p class="selectedRight">'+ '<img onClick="removeChecked($(this));" class="cancelChecked" src="../static/images/cancel.png" /></p></div>'; var checkedLabelArray = $(".selectedText"); if(checkedLabelArray<=0){ $("#allSelected").append(html); }else{ for(var i=0;i<checkedLabelArray.length;i++){//如果已经被选择 if($(checkedLabelArray[i]).text()==obj){ return false; } } } $("#allSelected").append(html); } function removeChecked(obj){ $(obj).parent().parent().remove(); } function ajaxLoadDesignerCall(data,obj){ var list = data.list; currentPage++; console.log(currentPage); var html =""; if(list.length>0){ for(var i=0;i<list.length;i++){ var gender = "女"; if(list[i].memberGender==1){ gender ="男"; } html+='<li class="designer_list_details" id='+(currentPage-1)+''+i+'box>'+ '<div class="user-info-banner">'+ '<div class="grid-730 left author-info">'+ '<div class="author-portrait left">'+ '<a href="#" title="" class="author-portrait-container">'+ '<div class="portrait-cover"></div>'+ '<img src="../static/images/'+list[i].memberPic+'" style="float:left" width="115px" height="115px" alt="" style="border:0px;"> </a> </div></div>'+ '<div class="designer_list_details_info">'+ '<p>'+list[i].memberName+'<img title="添加关注" class="addClass" src="../static/images/add.png" /></p>'+ '<p>'+gender+'</p>'+ '<p>粉丝/'+list[i].fans+' 作品:80</p></div>'+ '<div class="opus_images_list">'+ '<a href="javascipt:void(0);">'+ '<img src="../static/attachment/1.jpg" width="100" height="75"/></a>'+ '<a href="javascipt:void(0);">'+ '<img src="../static/attachment/1.jpg" width="100" height="75"/></a>'+ '<a href="javascipt:void(0);">'+ '<img src="../static/attachment/1.jpg" width="100" height="75"/></a>'+ '<a href="javascipt:void(0);">'+ '<img src="../static/attachment/1.jpg" width="100" height="75"/></a></div></div></li>'; } $("#layout_designer_list").append(html); var timeHtml = '<li><div class="time">'+Number(((currentPage-2)*10)+1)+'-'+Number(((currentPage-1)*10)+1)+'</div><div class="version">第'+(currentPage-1)+'页</div><div class="number" onclick="hrefCurrentPage(\''+currentPage+'0box\');" info='+(currentPage-1)+'0box></div></li>'; $("#timeline").append(timeHtml); }else{ $(".desigenerLoadingMore").html("已经全部加载完毕"); $(window).unbind(); } }
JSP主要代码:
<div class="designerList" id="10box"><!-- start designerList --> <ul class="layout_designer_list" id="layout_designer_list"> <c:forEach var="mentity" items="${list}"> <li class="designer_list_details"><!-- start designer_list_details--> <div class="user-info-banner"><!-- start user-info-banner--> <div class="grid-730 left author-info"><!-- start author-info--> <div class="author-portrait left"> <!-- start author-portrait--> <a href="#" title="" class="author-portrait-container"> <div class="portrait-cover"></div> <img src="${ctx}/static/images/${mentity.memberPic}" style="float:left" width="115px" height="115px" alt="" style="border:0px;"> </a> </div><!-- end author-portrait--> </div><!-- end author-info--> <div class="designer_list_details_info"><!-- start designer_list_details_info --> <p>${mentity.memberName} <img title="添加关注" class="addClass" src="${ctx}/static/images/add.png" /></p> <p> <c:if test="${mentity.memberGender==1}">男</c:if> <c:if test="${mentity.memberGender==2}">女</c:if>/${mentity.city}/销售 </p> <p>粉丝/${mentity.fans} 作品:80</p> </div><!-- end designer_list_details_info --> <div class="opus_images_list"> <a href="javascipt:void(0);"> <img src="${ctx}/static/attachment/1.jpg" width="100" height="75"/> </a> <a href="javascipt:void(0);"> <img src="${ctx}/static/attachment/2.jpg" width="100" height="75"/> </a> <a href="javascipt:void(0);"> <img src="${ctx}/static/attachment/3.jpg" width="100" height="75"/> </a> <a href="javascipt:void(0);"> <img src="${ctx}/static/attachment/4.jpg" width="100" height="75"/> </a> </div> </div><!-- end user-info-banner--> </li><!-- end designer_list_details--> </c:forEach> </ul> </div><!--end designerList -->
相关推荐
本示例“自定义ListView仿QQ空间下拉图片放大效果”由雷惊风实现,旨在模仿QQ空间顶部图片在用户下拉时的放大动画,当用户松手时,图片会有一个反弹的效果。这一功能的实现涉及到多个Android开发的关键知识点,包括...
在Android应用开发中,"仿qq空间实现下拉刷新上拉加载"是一个常见的功能需求,主要涉及到了Android UI设计、滚动事件处理、网络请求以及数据加载等多个知识点。下面将详细阐述这些技术点。 1. **SwipeRefreshLayout...
博客《PullScrollView详解(一)——自定义控件属性》深入探讨了如何自定义这个控件,以满足特定的交互需求。通过阅读博客并分析提供的源码,我们可以学习到以下几个重要的知识点: 1. **自定义控件**:在Android中...
在iOS开发中,UIPickerView是一个非常常用的组件,它用于展示一系列可滚动的选项,比如日期选择、时间选择或者是下拉列表。这个压缩包“IOS应用源码——自定义风格UIPickerView.rar”显然包含了一个关于如何自定义...
本压缩包文件"安卓Android源码——自定义表格自动刷新数据.zip"提供了相关的源码示例,帮助开发者深入理解这一功能的实现。以下是关于这个主题的详细知识讲解。 1. **自定义表格组件**: 安卓系统默认的表格控件`...
本教程将详细讲解如何利用自定义控件和PopupWindow实现一个仿58同城样式的下拉菜单。 首先,我们要了解什么是自定义控件。在Android系统中,虽然内置了大量的视图组件,如TextView、Button等,但这些组件可能无法...
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
在移动端开发中,下拉翻页效果是一种常见的用户体验设计,它允许用户通过在屏幕上向下滚动来加载更多内容,通常用于无限滚动列表或者分页浏览。这种效果在新闻、社交媒体、电商应用等场景中广泛使用,因为可以有效地...
本项目“jQuery自定义报警时间轴代码”是为开发者提供的一种功能强大的工具,它允许用户模拟移动报警器的时间轴,并且可以自定义设置报警区间。 这个时间轴代码的核心功能包括: 1. **报警类型选择**:用户可以...
在Android应用开发中,创建一个类似美团或淘宝的下拉筛选菜单是一项常见的需求。这个功能可以为用户提供方便快捷的筛选选项,提升用户体验。本篇将详细介绍如何使用PopupWindow结合ListView来实现这样的`...
【仿QQ下拉刷新】是一种常见的移动应用交互设计,它让用户在顶部下拉时触发页面内容的刷新。这种设计在QQ等社交应用中被广泛采用,后来成为了许多Android和iOS应用的标准特性。实现这一功能主要涉及到滚动视图、动画...
总的来说,"Android-下拉刷新——卡打印机效果"是一个融合了Android视图动画、事件监听和自定义View技术的实例,它展示了Android开发中如何通过创新的交互设计提升用户体验。通过研究和实践这个案例,开发者不仅可以...
在Android开发中,Spinner是一种常用的UI组件,它用于实现下拉选择菜单的功能,类似于iOS中的PickerView。在很多场合,开发者需要对Spinner进行自定义,以满足特定的设计需求。本篇将详细介绍如何利用Spinner和`...
Spinner是Android中的一个下拉选择控件,它提供了用户友好的交互方式,允许用户在一组预设选项中进行选择。 **1. Spinner的基本使用** Spinner的使用主要包括两步:创建Spinner对象和设置数据源。创建Spinner通常在...
除了EGORefreshTableHeaderView,还有其他类似的库,如MJRefresh,它提供了更多自定义选项和更简单的API,可以实现上拉加载更多和下拉刷新的功能。这些插件都大大简化了开发者实现滚动刷新功能的过程,使得应用更加...
Android UI设计之<十三>自定义ScrollView,实现QQ空间阻尼下拉刷新和渐变菜单栏效果,详http://blog.csdn.net/llew2011/article/details/52626148
在安卓(Android)开发中,创建自定义的用户界面是提升应用用户体验的关键步骤之一。本实例源码主要涉及了自定义单选对话框、多选对话框以及popwindow窗口的实现,这些都是Android应用中常见的交互元素。下面我们将...
本项目涉及的是使用jQuery实现的一种特殊效果——树型下拉时间轴,这种效果通常用于展示一系列按时间顺序排列的事件,用户可以以折叠或展开的方式查看这些事件,类似于QQ空间的时间轴设计。 时间轴是一种直观的数据...
在iOS开发中,创建自定义下拉菜单是一项常见的任务,特别是在设计类似QQ安全中心这样的应用时,为了提供用户友好的交互体验,这类菜单通常用于展示多种功能选项。本项目名为"ios-仿QQ安全中心下拉菜单.zip",显然...
本话题将深入探讨如何自定义`select`分组下拉菜单的样式,以实现更美观且功能丰富的交互效果。 首先,我们需要了解`<select>`的基本结构。一个带有分组的`select`通常会包含`<optgroup>`元素来创建选项组,以及`...