ys_scroll.css
.ys-scroll-wrapper{ position:relative; overflow: auto; -webkit-overflow-scrolling: touch; } .ys-scroll-wrapper .ys-scroll-content{ min-height:100%; } /* loading-top */ .ys-scroll-wrapper .loading-top { display:block; width:100%; height:40px; line-height: 40px; text-align: center; } /* loading-bottom */ .ys-scroll-wrapper .loading-bottom { display:block; width:100%; height:40px; line-height: 40px; text-align: center; } /* loading-bottom */ .ys-scroll-wrapper .loading-end { display:none; width:100%; height:40px; line-height: 40px; text-align: center; }
ys_scroll.js
(function($){ var defaultSettings = { hasArrivedEnd:false,// 是否已经到底部 pulldownCallback:function(){ // 下拉回调 console.log("pull down ... "); }, pullupCallback:function(){ // 上拉回调 console.log("pull up ... "); } }; function render(target,settings){ var container = target; var childrenNode = $(container).children().remove(); $(container).addClass("ys-scroll-wrapper"); $(container).append("<div class=‘loading-top‘>加载中...</div>"); $(container).append("<div class=‘ys-scroll-content‘></div>"); $(container).append("<div class=‘loading-bottom‘>加载更多...</div>"); $(container).append("<div class=‘loading-end‘>已经到底了</div>"); $(container).find(".ys-scroll-content").append(childrenNode); $(container).scrollTop(LOADING_BAR_HEIGHT); $(container).data("settings",settings); return container; } function bindEventHandlers(target,container,settings){ var loadingTopRevertTimeout = null; var loadingTopEndTimeout = null; var loadingBottomRevertTimeout = null; var loadingBottomTimeout = null; var pulldownCallback = settings.pulldownCallback; var pullupCallback = settings.pullupCallback; function clearTimeouts(){ clearTimeout(loadingTopRevertTimeout); clearTimeout(loadingTopEndTimeout); clearTimeout(loadingBottomRevertTimeout); clearTimeout(loadingBottomTimeout); } function scrollHandler(){ clearTimeouts(); var loadingTop = false; if(arriveLoadingTopStart(container)){ loadingTopRevertTimeout = setTimeout(function(){ loadingTopRevert(container); },RESPONSE_DELAY); loadingTop = true; } if(arriveLoadingTopEnd(container)){ clearTimeouts(); loadingTopEndTimeout = setTimeout(function(){ resetLoading(container); pulldownCallback(); },RESPONSE_DELAY); loadingTop = true; } var hasArrivedEnd = $(container).data("settings").hasArrivedEnd; if(hasArrivedEnd||loadingTop){ // 如果已经到底了不需要额外操作 return; } if(arriveLoadingBottomStart(container)){ loadingBottomRevertTimeout = setTimeout(function(){ loadingBottomRevert(container); },RESPONSE_DELAY); } if(arriveLoadingBottomEnd(container)){ clearTimeouts(); loadingBottomTimeout = setTimeout(function(){ pullupCallback(); },RESPONSE_DELAY) } } var hasPressed = false; $(container).on("touchstart",function(event){ hasPressed = true; clearTimeouts(); stopAnimation(container); }); $(container).on("touchmove",function(event){ hasPressed = true; clearTimeouts(); stopAnimation(container); var clientX = event.originalEvent.changedTouches[0].clientX; var clientY = event.originalEvent.changedTouches[0].clientY; if(clientY<0||clientX<0){ scrollHandler(); } }); $(container).on("touchend touchcancel",function(event){ scrollHandler(); hasPressed = false; }); $(container).scroll(function(){ if(hasPressed||reverting){ return; } scrollHandler(); }); } var RESPONSE_DELAY = 800; // 触发延迟 var ANIMATION_DURATION = 300; // 动画持续时间 var LOADING_BAR_HEIGHT = 40; // loading bar 高度 var reverting = false; // 动画正在恢复 function stopAnimation(container){ $(container).stop(true); reverting = false; } function loadingTopRevert(container){ reverting = true; $(container).animate({ "scrollTop":LOADING_BAR_HEIGHT+"px" },ANIMATION_DURATION,function(){ reverting = false; }); } /* 判断达到 Loading-top开始处 */ function arriveLoadingTopStart(container){ var scrollTop = $(container).scrollTop(); if(scrollTop<LOADING_BAR_HEIGHT){ return true; } return false; } /* 判断达到 Loading-top结束处 */ function arriveLoadingTopEnd(container){ var scrollTop = $(container).scrollTop(); if (scrollTop<1) { return true; } return false; } function loadingBottomRevert(container){ reverting = true; var clientHeight = $(container).height(); var scrollTop = $(container)[0].scrollHeight-LOADING_BAR_HEIGHT-clientHeight; $(container).animate({ "scrollTop":scrollTop+"px" },ANIMATION_DURATION,function(){ reverting = false; }); } /* 判断到达 Loading Bottom 开始处 */ function arriveLoadingBottomStart(container){ var scrollTop = $(container).scrollTop(); var scrollHeight = $(container)[0].scrollHeight; var clientHeight = $(container).height(); if (scrollTop + clientHeight+LOADING_BAR_HEIGHT>= scrollHeight) { return true; } return false; } /* 判断到达 Loading Bottom 结束处 */ function arriveLoadingBottomEnd(container){ var scrollTop = $(container).scrollTop(); var scrollHeight = $(container)[0].scrollHeight; var clientHeight = $(container).height(); if (scrollTop + clientHeight+1> scrollHeight) { return true; } return false; } /* 重设 loading */ function resetLoading(container){ $(container).data("settings").hasArrivedEnd=false; $(container).find(".loading-bottom").show(); $(container).find(".loading-end").hide(); } /* 设置loading end */ function setLoadingEnd(container){ $(container).data("settings").hasArrivedEnd=true; $(container).find(".loading-bottom").hide(); $(container).find(".loading-end").show(); } var options = { ysScroll:function(settings) { var mergedSettings = {}; $.extend(mergedSettings,defaultSettings,settings); $(this).each(function(){ var container = render(this,settings); $(container).data("settings",settings); bindEventHandlers(this,container,mergedSettings); }); }, ysScrollRefresh:function(){ if(arriveLoadingTopStart(this)){ loadingTopRevert(this); } if(arriveLoadingBottomStart(this)){ loadingBottomRevert(this); } }, ysScrollLoadEnd:function(){ setLoadingEnd(this); } }; $.fn.extend(options); })(jQuery);
测试页面 scroll.html
<!DOCTYPE html> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta name="format-detection" content="telephone=no"> <link href="css/common/ys_scroll.css" rel="stylesheet"> <style> html,body,.container{ height:100%; margin:0; padding:0; } </style> </head> <body> <div class="container"> <ul> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> <li>这是测试数据...</li> </ul> </div> <script src="dist/js/jquery-1.11.3.min.js"></script> <script src="js/common/ys_scroll.js"></script> <script> var dataHtml = $(".container ul").html(); $(".container ").ysScroll({ pulldownCallback:function(){ // 下拉回调 console.log("pull down ... "); $(".container ul").html(dataHtml); $(".container ").ysScrollRefresh(); }, pullupCallback:function(){ // 上拉回调 console.log("pull up ... "); $(".container ul").append(dataHtml); $(".container ").ysScrollRefresh(); } }); </script> </body> </html>
注:容器使用前要给其设置一个固定的高度。当触发pulldownCallback,pullupCallback回调后一定要使用$(".container").ysScrollRefresh();重置容器。
原文地址:http://antlove.blog.51cto.com/10057557/1844427