在高性能要求的大型移动端项目中,使用移动端事件时必须的。而常规的固定定位在移动端的兼容性不是很友好。实际开发中的常见布局便是顶部标题栏固定于顶部,导航固定于底部,中间为可滑动的内容区域。因此封装移动端的滑动组件,就显得很有必要了。
而实际开发中,淘宝团队也是这种解决方案。
函数如下:
pomeloTween.js下载地址:https://github.com/pomelott/pomeloTween
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,user-scalable=no"/> <title>自定义滑动</title> <style type="text/css"> body { margin: 0; } body, html { height: 100%; overflow: hidden; position: relative; } header { height: 40px; font-size: 20px; color: #fff; text-align: center; background: #000; line-height: 40px; } footer { position: absolute; left: 0; right: 0; bottom: 0; height: 40px; color: #fff; text-align: center; background: #000; line-height: 40px; } #wrap { position: absolute; left: 0; right: 0; top: 40px; bottom: 40px; overflow: hidden; } #list { margin: 0; padding: 0; list-style: none; } #list li { line-height: 30px; text-indent: 20px; font-size: 16px; border-bottom: 1px solid #000; } </style> <script type="text/javascript" src="pomeloTween.js"></script> <script type="text/javascript"> function createList(){ var list = document.querySelector('#list'); var inner = ""; for(var i = 0; i < 30; i++){ inner += "<li>这是第"+i+"个li</li>" } list.innerHTML = inner; } document.addEventListener('touchstart', function(e) { e.preventDefault(); }); window.onload = function(){ createList(); var wrap = document.querySelector('#wrap'); mScroll({ el:wrap, //滚动区域结点 offBar: true //是否禁止滚动条 }) }; function mScroll(init){ if(!init.el){ return; } var wrap = init.el; var inner = init.el.children[0]; var scrollBar = document.createElement("div"); var startPoint = 0; var startEl = 0; var lastY = 0; var lastDis = 0; var lastTime = 0; var lastTimeDis = 0; var maxTranslate = wrap.clientHeight - inner.offsetHeight; if(!init.offBar){ var scale = wrap.clientHeight/inner.offsetHeight; inner.style.minHeight = "100%"; scrollBar.style.cssText = "6px;background:rgba(0,0,0,.5);position:absolute;right:0;top:0;border-radius:3px;opacity:0;transition:.3s opacity;"; wrap.appendChild(scrollBar); } css(inner,"translateZ",0.01); inner.addEventListener('touchstart', function(e) { maxTranslate = wrap.clientHeight - inner.offsetHeight; if(!init.offBar){ if(maxTranslate >= 0) { scrollBar.style.display = "none"; } else { scrollBar.style.display = "block"; } scale = wrap.clientHeight/inner.offsetHeight; scrollBar.style.height = wrap.clientHeight * scale + "px"; } clearInterval(inner.timer); startPoint = e.changedTouches[0].pageY; startEl = css(inner,"translateY"); lastY = startEl; lastTime = new Date().getTime(); lastTimeDis = lastDis = 0; (init.offBar)||(scrollBar.style.opacity = 1); }); inner.addEventListener('touchmove', function(e) { var nowTime = new Date().getTime(); var nowPoint = e.changedTouches[0].pageY; var dis = nowPoint - startPoint; var translateY = startEl + dis; css(inner,"translateY",translateY); (init.offBar)||css(scrollBar,"translateY",-translateY*scale); lastDis = translateY - lastY; lastY = translateY; lastTimeDis = nowTime - lastTime; lastTime = nowTime; }); inner.addEventListener('touchend', function(e) { var type = "easeOut"; var speed = Math.round(lastDis / lastTimeDis*10); speed = lastTimeDis <= 0?0 :speed; var target = Math.round(speed*30 + css(inner,"translateY")); if(target > 0){ target = 0; type = "backOut"; } else if(target < maxTranslate){ target = maxTranslate; type = "backOut"; } MTween({ el:inner, target: {translateY:target}, time: Math.round(Math.abs(target - css(inner,"translateY"))*1.8), type: type, callBack: function(){ (init.offBar) || (scrollBar.style.opacity = 0); }, callIn: function(){ var translateY = css(inner,"translateY"); init.offBar||css(scrollBar,"translateY",-translateY*scale); } }); }); } </script> </head> <body> <header id="header">自定义滑动</header> <section id="wrap"> <ul id="list"> </ul> </section> <footer id="footer">底部导航</footer> </body> </html>