移动端会有默认事件,比如滚动条、长按菜单、选中文字等等,很多是我们不想要的,所以,我们做的时候,一般会阻止默认事件,然后自然就把所有的默认事件阻止了,包括滚动条,那么此时我们就要自己用代码实现滑屏效果了
实现的方法有很多,比如用定位,改变top值,但我们知道,改变top值,会不断的引起回流,是很影响性能的,所以我们尽量不要用这种方法,所以在移动端,实现移动效果,比较推荐的就是利用translate来改变了
说一下我的代码的大致效果:
- 滑动效果,内容随着手指的滑动而滑动,并且当手指离开的时候
- 会有缓冲效果(缓冲的距离是根据手指离开时的最后速度而定,速度越大缓冲的距离就越远,速度很小的时候,也就没有缓冲了)
- 添加了滚动条,如果内容多时,手指按下时滚动条就会出现,手指离开后滚动条消失
下面就是我的代码:代码中有详细的注释
注意:使用前,需要先引入我之前封装好的动画函数m.Tween.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,user-scalable=no"/> <script> document.addEventListener("touchstart",function(e){ e.preventDefault();//阻止默认事件 }) </script> <title>Title</title> <style> body{margin:0;} html,body{height:100%; overflow:hidden; position:relative;} ul,li{margin:0; padding:0;} li{list-style:none;} header{ height:40px; font-size:20px; color:#fff; background:#000; line-height:40px; text-align:center; } footer{ position:absolute; bottom:0; right:0; left:0; height:40px; line-height:40px; text-align:center; background:#000; color:#fff; } #wrap{ position:absolute; top:40px; left:0; right:0; bottom:40px; overflow:hidden; } #list li{ line-height:30px; text-indent:20px; font-size:16px; border-bottom:1px solid #000; } </style> </head> <script type="text/javascript" src="js/m.Tween.js"></script> <body> <header id="header">移动端滑屏</header> <section id="wrap"> <ul id="list"></ul> </section> <footer id="footer">一切都没变,只是以一种不同的方式呈现罢了</footer> </body> <script> //生成列表内容 function createList(){ var list = document.querySelector('#list'); var inner = ""; for(var i=0; i<200; i++){ inner+=`<li>这是第${i}个li</li>` } list.innerHTML = inner; } window.onload = function(){ createList(); var list = document.querySelector('#list'); var wrap = document.querySelector('#wrap'); var scrollBar = document.createElement('div'); var maxTranslate = 0; var startPoint = 0; var startEl = 0; var lastY = 0; var lastTime = 0; var lastTimeDis = 0; var lastDis = 0; var scale = wrap.clientHeight/list.offsetHeight; scrollBar.style.cssText = "width:6px; background:rgba(0,0,0,.5); position:absolute; right:0; top:0;opacity:0;transition:2s opacity; border-radius:3px;"; wrap.appendChild(scrollBar); scrollBar.style.height = wrap.clientHeight*scale+'px';//根据内容的多少来动态计算滚动条的长度,内容越多,则滚动条越短 list.style.minHeight = "100%";//让内容的最小高度与wrap高度保持一致 maxTranslate = wrap.clientHeight - list.offsetHeight; css(list,"translateZ",0.01);//开启3d硬件加速 list.addEventListener('touchstart',function(e){ clearInterval(list.timer);//当手指按下的时候清除掉MTween中的定时器,目的就是当手指按下的时候,如果动画还在执行,让其停止 startPoint = e.changedTouches[0].pageY; startEl = css(list,"translateY"); lastY = startEl; lastTime = new Date().getTime(); lastTimeDis = lastDis = 0; if(maxTranslate>=0){//如果内容的高度没有超出的时候,不让滚动条出现 scrollBar.style.display = "none"; }else{ scrollBar.style.display = "block"; } scrollBar.style.opacity = 1;//只有当我们手指按下时,滚动条才出现 //console.log(0) }) list.addEventListener('touchmove',function(e){ var nowPoint = e.changedTouches[0].pageY; var nowTime = new Date().getTime(); var dis = nowPoint - startPoint; var translateY = startEl + dis; css(list,"translateY",translateY); css(scrollBar,"translateY",-translateY*scale);//设置滚动条的移动距离 //下面是为我们的缓冲运动做准备(移动最后一点减去上一点的距离除以移动的最后一次时间减去上一次的时间, // 即为最后的移动速度,然后我们希望根据最后的速度来决定缓冲的距离) lastDis = translateY - lastY; lastTimeDis = nowTime - lastTime; lastTime = nowTime; lastY = translateY; }) list.addEventListener('touchend',function(){ var type = "easeOut"; var speed = Math.round(lastDis/lastTimeDis*10);//求最后的移动速度 speed = lastTimeDis<=0?0:speed;//如果速度很小的话,就不用在做缓冲运动了 var target = Math.round(speed*30+css(list,"translateY"));//(求缓冲的最终位置) if(target>0){ target = 0; type = "backOut"; }else if(target<maxTranslate){ target = maxTranslate; type = "backOut"; }//添加想要的运动形式,就要用到我们的MTween封装函数 MTween({ el:list, target:{translateY:target}, time:Math.round(Math.abs(target - css(list,"translateY"))*2), type:type, callBack:function(){//添加回调函数,当缓冲动画执行完之后,让滚动条消失 scrollBar.style.opacity = 0; }, callIn:function(){ var translateY = css(list,"translateY"); css(scrollBar,"translateY",-translateY*scale);//添加同步函数,缓冲运动的时候,让滚动条滚动的距离也随着变化 } }); }) } </script> </html>