移动端 触屏滑动条菜单(完善版)



<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=320,user-scalable=no" />

<title>菜单条</title>
</head>

<body>

<style style='display:none' contentEditable>
*{ margin:0; padding:0;}
ul,li{ margin:0; padding:0; list-style:none;}

#outer{ border:1px  solid red; 300px; height:46px; margin:20px auto; text-align:center; vertical-align:middle; line-height:46px; position:relative; overflow:hidden; background:#eee;}
#outer:hover{ border-color:#333; cursor:pointer;}
#inner{ position:absolute; left:0; top:1px; height:44px; line-height:44px; 300px; background:#666;  text-align:left; clear:both; overflow:hidden;}
#inner li{ auto; height:44px; float:left; display:inline; padding:0 15px; text-align:center;  }
#inner li:hover{ background:#333;}
#inner li a{font-size:14px; color:#fff; display:inline;auto; height:44px; line-height:44px; text-decoration:none;}
.translateZ{ -webkit-transform:translateZ(0);transform:translateZ(0);-webkit-backface-visibility: hidden;backface-visibility: hidden;}

.classtest{ background:#333;}
</style>

<div id="outer">
    <ul id="inner" >
        <li><a href="">首页start</a></li>
        <li><a href="">美剧1</a></li>
        <li><a href="">电影1</a></li>
        <li><a href="">购物1</a></li>
        <li><a href="">时尚1</a></li>
        <li><a href="">新闻1</a></li>
        <li><a href="">其他1</a></li>
        <li><a href="">热点1</a></li>
        <li><a href="">电视1</a></li>
        <li><a href="">历史1</a></li>
         <li><a href="">首页2</a></li>
        <li><a href="">美剧2</a></li>
        <li><a href="">电影2</a></li>
        <li><a href="">购物2</a></li>
        <li><a href="">时尚2</a></li>
        <li><a href="">新闻2</a></li>
        <li><a href="">其他2</a></li>
        <li><a href="">热点2</a></li>
        <li><a href="">电视2</a></li>
        <li><a href="">结尾end</a></li>
    </ul>
</div>


touches:当前屏幕上所有手指的列表
targetTouches:当前dom元素上手指的列表,尽量使用这个代替touches
changedTouches:涉及当前事件的手指的列表,尽量使用这个代替touches
<script src="../js/jquery-1.9.1.min.js"></script>
<script>
window.onload=function(){
	
	   function getStyle(obj,attr){
       return obj.currentStyle? obj.currentStyle[attr]:getComputedStyle(obj,false)[attr];
       }
	   
	  var support = document.body.classList==undefined ? false : true ;
	  
	  var outer=document.getElementById("outer");
      var inner=document.getElementById("inner");
	  var li=inner.getElementsByTagName("li");
	  var innerWd=0,i=0;
	  for(;i<li.length;i++){
		   innerWd+=li[i].offsetWidth;
	  }
	  inner.style.width=innerWd+'px';
     
    
	  var startX=0;
	  var alls=0;
	  var moveLeft=0;
	  var iSpeedX = 0;
	  var prevX = 0;
	  var timer = null;
	  var resetStartX=true;
	  var maxDistance=parseInt(outer.offsetWidth-innerWd); //最大滑动距离
	  
	  inner.addEventListener("touchstart",start,false); 
	  function start(e){
		   if(inner.offsetWidth<outer.offsetWidth)return;//如果内部元素小于外框 不需要滑动

		   var e=e||window.event;
                   e.preventDefault();
		    var   touchs=e.touches[0],
               resetStartX=true;;
            //startX=prevX=touchs.pageX;
			   startX=touchs.pageX;
	           prevX=touchs.pageX;
			
		       alls=this.offsetLeft;
		 
	       inner.addEventListener("touchmove",move,false);
	       inner.addEventListener("touchend",end,false);
		  
	   }
	  
	   function move(e){
		 var e=e||window.event;
		 if (e.touches.length > 1 || e.scale && e.scale !== 1) return; // 当屏幕有多个touch或者页面被缩放过,就不执行move操作
		 var touchs=e.changedTouches[0];
		 
	       iSpeedX = touchs.pageX - prevX;//获取出手一瞬间的速度
		   prevX = touchs.pageX;//当前的始终覆盖上一个
		   moveLeft=touchs.pageX-startX;
		
		   var that=this;
		    
		   if(that.offsetLeft>=0){
			     if(resetStartX){
					 startX=touchs.pageX;
					 resetStartX=false;
					 }
			   that.style.left=moveLeft/3+alls+'px'; 
			   
			}else if(that.offsetLeft<=maxDistance){
				if(resetStartX){
					 startX=touchs.pageX;
					 resetStartX=false;
				  }
			   that.style.left=moveLeft/3+alls+'px';
			  
			}else{
			    that.style.left=moveLeft+alls+'px';	   
		    }
		   
		   //this.style.webkitTransform='translateZ(0)'; //移动时候  缓存到GPU层
		   that.classList.add('translateZ'); //classList 对已经增加的样式 不在判断是否添加  GPU缓存hack 
		   e.preventDefault();
	   }
	  
	   function end(){
		
		 var self=this;
		 clearInterval(timer);
		 
		 timer=setInterval(function(){
			    
				  if(Math.abs(iSpeedX)<=1||self.offsetLeft>50||self.offsetLeft<maxDistance-50){
					     clearInterval(timer);
							 //if(self.classList.contains('translateZ')){  //滚动停止 结束时候回收GPU 垃圾
//		                         // self.classList.remove('translateZ'); //不知道怎么删除这样样式  
//								 // self.setAttribute("class",'');
//		                       } 

                           if(self.offsetLeft>=0){
							  $(inner).animate({left:0},300,function(){
								  self.classList.remove('translateZ');   //移除PGU hack
								  }); 
						    } 
						   if(self.offsetLeft<maxDistance){   
						   $(inner).animate({left:maxDistance+'px'},300,function(){
							    self.classList.remove('translateZ');   //移除PGU hack
							    }); 
						   }
								    
				  }else{
			        iSpeedX *= 0.95;
					self.style.left = parseInt(self.offsetLeft + iSpeedX) + 'px';
				 }
			 },20);
		 
		
	    self.removeEventListener("touchmove",move,false);
	    self.removeEventListener("touchend",end,false); 
	    //self.style.webkitTransform=''; 	  
	  } 
	  
	 
}
	
</script>
</body>
</html>

优化滑动 setTimeout 相对减少时间计数

 function end(){
		
		 var self=this;
		 clearTimeout(timer);
		 
		 timer=setTimeout(function(){
			    
				  if(Math.abs(iSpeedX)<=1||self.offsetLeft>50||self.offsetLeft<maxDistance-50){
					     clearTimeout(timer);
							 //if(self.classList.contains('translateZ')){  //滚动停止 结束时候回收GPU 垃圾
//		                         // self.classList.remove('translateZ'); //不知道怎么删除这样样式  
//								 // self.setAttribute("class",'');
//		                       } 
                         

                           if(self.offsetLeft>=0){
							  $(inner).animate({left:0},300,function(){
								  self.classList.remove('translateZ');   //移除PGU hack
								  }); 
						    } 
						   if(self.offsetLeft<maxDistance){   
						   $(inner).animate({left:maxDistance+'px'},300,function(){
							    self.classList.remove('translateZ');   //移除PGU hack
							    }); 
						   }
								    
				  }else{
			        iSpeedX *= 0.95;
					self.style.left = parseInt(self.offsetLeft + iSpeedX) + 'px';
						console.log('setTimeoutsss');
					setTimeout(arguments.callee,16)
				 }
			 },16);
		 
		
	    self.removeEventListener("touchmove",move,false);
	    self.removeEventListener("touchend",end,false); 
	    //self.style.webkitTransform=''; 	  
	  } 
	  

  

优化滑动  requestAnimationFrame 大幅减少时间计数

       function end(){
        
         var self=this,
         stopFlag=null;
          
               function  sliderMove(){ 
                  if(Math.abs(iSpeedX)<=1||self.offsetLeft>50||self.offsetLeft<maxDistance-50){
                          
                           if(self.offsetLeft>=0){
                              $(inner).animate({left:0},300,function(){
                                  self.classList.remove('translateZ');   //移除PGU hack
                                  }); 
                            } 
                           if(self.offsetLeft<maxDistance){   
                           $(inner).animate({left:maxDistance+'px'},300,function(){
                                self.classList.remove('translateZ');   //移除PGU hack
                                }); 
                           }
                            window.cancelAnimationFrame(stopFlag);//可以取消该次动画
                            stopFlag=null;
                            sliderMove=null;  //清空对象
                          console.log('requestAnimationFramessss'+sliderMove);
                                    
                  }else{
                    iSpeedX *= 0.95;
                     self.style.left = parseInt(self.offsetLeft + iSpeedX) + 'px';
                    console.log('滑动时候requestAnimationFrame次数');
                    stopFlag=requestAnimationFrame(arguments.callee);
                 }
               }
         sliderMove();
        
        self.removeEventListener("touchmove",move,false);
        self.removeEventListener("touchend",end,false); 
        //self.style.webkitTransform='';       
      } 

requestAnimationFrame兼容处理:

;(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
    }
    if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) {
        var currTime = new Date().getTime();
        var timeToCall = Math.max(0, 16 - (currTime - lastTime));
        var id = window.setTimeout(function() {
            callback(currTime + timeToCall);
        }, timeToCall);
        lastTime = currTime + timeToCall;
        return id;
    };
    if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}());



// requestAnimationFrame polyfill by Erik Möller.
// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
// MIT license
if (!Date.now)
  Date.now = function() { return new Date().getTime(); };
(function() {
  'use strict';
  var vendors = ['webkit', 'moz'];
  for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
    var vp = vendors[i];
    window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
    window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
                   || window[vp+'CancelRequestAnimationFrame']);
  }
  if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
    || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
    var lastTime = 0;
    window.requestAnimationFrame = function(callback) {
      var now = Date.now();
      var nextTime = Math.max(lastTime + 16, now);
      return setTimeout(function() { callback(lastTime = nextTime); },
                nextTime - now);
    };
    window.cancelAnimationFrame = clearTimeout;
  }
}());

  

其他问题 用户误触, css3持续时间  translate位移性能, touchmove 以及快速滑动 gpu的 合理调度

  
	 $(document).ready(function(e) {
        
   
	   function getStyle(obj,attr){
       return obj.currentStyle? obj.currentStyle[attr]:getComputedStyle(obj,false)[attr];
       }
	   
	  var support = document.body.classList==undefined ? false : true ;
	  
	  var outer=document.getElementById("outer");
      var inner=document.getElementById("inner");
	  var li=inner.getElementsByTagName("li");
	  var innerWd=0,i=0;
	  for(;i<li.length;i++){
		   innerWd+=li[i].offsetWidth;
	  }
	  inner.style.width=innerWd+'px';
     
    
	  var startX=0;
	  var alls=0;
	  var moveLeft=0;
	  var iSpeedX = 0;
	  var prevX = 0;
	  var timer = null;
	  var resetStartX=true;
	  var maxDistance=parseInt(outer.offsetWidth-innerWd); //最大滑动距离
	  var stopFlag=null;
	  
	  inner.addEventListener("touchstart",start,false); 
	  function start(e){
		   if(inner.offsetWidth<outer.offsetWidth)return;//如果内部元素小于外框 不需要滑动

		   var e=e||window.event;
		    e.preventDefault();
		      var touchs=e.touches[0];
               resetStartX=true;;
            //startX=prevX=touchs.pageX;
			   startX=touchs.pageX;
	           prevX=touchs.pageX;
			
		       alls=this.offsetLeft;
		  
		   inner.classList.add('translateZ'); //classList 对已经增加的样式 不在判断是否添加  GPU缓存hack 
		    
	       inner.addEventListener("touchmove",move,false);
	       inner.addEventListener("touchend",end,false);
		  
	   }
	  
	   function move(e){
		 var e=e||window.event;
		 e.preventDefault();
		 if (e.touches.length > 1 || e.scale && e.scale !== 1) return; // 当屏幕有多个touch或者页面被缩放过,就不执行move操作
		 var touchs=e.changedTouches[0];
		 
	       iSpeedX = touchs.pageX - prevX;//获取出手一瞬间的速度
		   prevX = touchs.pageX;//当前的始终覆盖上一个
		   moveLeft=touchs.pageX-startX;
		
		   var that=this;
		    
		   if(that.offsetLeft>=0){
			     if(resetStartX){
					 startX=touchs.pageX;
					 resetStartX=false;
					 }
					 
					 var  topNum=(touchs.pageX - startX)/3;
			         that.style.left =topNum  + 'px';
			 
			   
			}else if(that.offsetLeft<=maxDistance){
				if(resetStartX){
					 startX=touchs.pageX;
					 resetStartX=false;
				  }
			       
				    var midNum= (touchs.pageX - startX)/3 + (maxDistance);
			      that.style.left = midNum+ 'px';
			  
			}else{
				
				  var botNum=touchs.pageX - startX + alls;
				 that.style.left =botNum  + 'px';    
		    }
		   
		   //this.style.webkitTransform='translateZ(0)'; //移动时候  缓存到GPU层
		  
		  
	   }
	  
	  
	
	   function end(e){
		 var e=e||window.event;
		 e.preventDefault();
		 var self=this;
		   var touchs=e.changedTouches[0];
	     var minDis= touchs.pageX-startX;
		  
			   function  sliderMove(){ 
				  if(Math.abs(iSpeedX)<=1||self.offsetLeft>50||self.offsetLeft<maxDistance-50){
						  
                           if(self.offsetLeft>=0){
							   console.log('llllllllllllllll');
							  $(inner).animate({left:0},300,function(){
								  self.classList.remove('translateZ');   //移除PGU hack
								  }); 
						    } 
						   if(self.offsetLeft<maxDistance){   
						   $(inner).animate({left:maxDistance+'px'},300,function(){
							    self.classList.remove('translateZ');   //移除PGU hack
							    }); 
						   }
						    window.cancelAnimationFrame(stopFlag);//可以取消该次动画
							stopFlag=null;
							sliderMove=null;  //清空对象
						  console.log('requestAnimationFramessss'+sliderMove);
								    
				  }else{
			        iSpeedX *= 0.95;
					 self.style.left = parseInt(self.offsetLeft + iSpeedX) + 'px';
					console.log('滑动时候requestAnimationFrame次数');
					stopFlag=requestAnimationFrame(arguments.callee);
				 }
			   }
			   
			   if(Math.abs(minDis)>5) { //减少tap时候 bug  有时候轻轻一碰带来的问题 用户事项tap 时候
		    sliderMove();
			}
		
	
	    self.removeEventListener("touchmove",move,false);
	    self.removeEventListener("touchend",end,false); 
	    //self.style.webkitTransform=''; 	  
		
	  } 
	  
	 
//}
 });

  



本文地址:http://www.cnblogs.com/surfaces/

原文地址:https://www.cnblogs.com/surfaces/p/4560435.html