2012-04-24 27 views
5

Tôi đang cố gắng triển khai phương pháp cuộn tùy chỉnh đơn giản trong ứng dụng web di động của mình. Tôi đang gặp rắc rối với việc di chuyển dọc, nơi tôi muốn có một chút hiệu ứng động lực nếu trang là 'flicked'.Làm thế nào để phát hiện một 'flick' sau khi kéo?

Vấn đề là phát hiện cử chỉ "rung", (vận tốc và có lẽ là chiều dài của cử chỉ đó) sau khi cử chỉ kéo, thay đổi hướng và những gì không. Hy vọng bạn hiểu ý tôi là gì, bạn có thể kéo trang lên hoặc xuống và ở cuối kéo, tôi muốn phát hiện nếu có một cú nhấp chuột.

Làm cách nào để tách hai? Logic như thế nào?

Rất cám ơn vì đã trợ giúp.

Mã: (xin lỗi nếu đoạn trích này là một chút của một mớ hỗn độn)

var Device = function() { 

    //define some private variablees 
    var startY, 
     startX, 
     startTime, 
     deltaY = 0, 
     deltaX = 0, 
     lastY, 
     currentPage, 
     nextPage, 
     prevPage, 
     directionY, 
     lastTime, 
     pages, 
     pane, 
     offsetX = 0, 
     offsetY = 0, 
     isPanning, 
     isScrolling, 
     isTouch = "ontouchstart" in window; 


    return { 



     init: function() { 

     document.getElementById('frame').addEventListener(isTouch ? 'touchstart' : 'mousedown', Device.onTouchStart, false); 


      //get all panes in an array 
      panes = document.querySelectorAll('.pane'); 


     },  

onTouchStart: function (evt) { 

      //get X and Y of the touch event 
      var touch = isTouch ? event.touches[0] : event; 
      startY = touch.clientY; 

      //add listener for touch move and end 
      document.addEventListener(isTouch ? 'touchmove' : 'mousemove', Device.onTouchMove, false); 
      document.addEventListener(isTouch ? 'touchend' : 'mouseup', Device.onTouchEnd, false); 

      startTime = new Date(); 
     }, 
     onTouchMove: function (evt) { 

       //get X and Y of the touch event 
       var touch = isTouch ? event.touches[0] : event; 

       currentY = touch.clientY; 

       //calc touch length 
       deltaY = currentY - startY;    


       //Detect if scroll is bigger than threshold 5px 
       if (Math.abs(deltaY) > 5 && !isPanning) { 



         isScrolling = true; 


         //get the element 
          pane = panes[0]; 

         //set new position 
         offsetY = pane.lastOffset + deltaY; 

                //call animation 
         Device.scrollTo(pane,0,offsetY); 

        } 

      //detect last direction  
      directionY = (lastY >= currentY) ? 1 : 0; 


       //roll over last variables 
       lastY = currentY; 
       lastTime = new Date(); 
     }, 

     onTouchEnd: function() { 

     //timing 
       var endTime = new Date(); 
       var velocity = (endTime - lastTime).toFixed(0); 


      console.log('velocity: ' + velocity); 

//TEMPORARY 
pane.lastOffset = offsetY; 


       isScrolling = false; 

       //housekeeping 
       document.removeEventListener(isTouch ? 'touchmove' : 'mousemove', Device.onTouchMove, false); 
       document.removeEventListener(isTouch ? 'touchend' : 'mouseup', Device.onTouchEnd, false); 

      //call for momentum 
      Device.doMomentum(velocity); 

     }, 
     scrollTo: function(el,x,y) { 
     if (el) { 

       el.style['-webkit-transition-timing-function'] = ''; 
       el.style['-webkit-transition-duration'] = '0ms'; 
       el.style[ 'WebkitTransform' ] = 'translate3d('+x+'px,'+y+'px, 0px)'; 
     } 
     }, 
     animateTo: function(el,x,y) { 
     if (el) { 
       el.style['-webkit-transition-timing-function'] = 'cubic-bezier(0,0,0.25,1)'; 
       el.style['-webkit-transition-duration'] = '300ms'; 
       el.style[ 'WebkitTransform' ] = 'translate3d('+x+'px,'+y+'px, 0px)'; 
     } 
     }, 
     doMomentum: function(velocity) { 



     console.log((directionY == 1) ? 'up': 'down'); 
     console.log('pane.lastOffset: ' + pane.lastOffset); 
     var endPosition; 

      if (directionY == 1) { 
     endPosition = pane.lastOffset - velocity; 

     } else { 

     endPosition = parseFloat(pane.lastOffset) + parseFloat(velocity); 
     } 

     console.log(endPosition); 

     Device.animateTo(pane,0,endPosition); 

     pane.lastOffset = endPosition; 


     } 

Trả lời

0

FYI, những gì tôi đã làm chỉ đơn giản là sử dụng thời gian trôi qua giữa onTouchMove và sự kiện onTouchEnd -event.

Về cơ bản, tôi có một biến ngày đó liên tục ghi đè chính nó trong onTouchMove callback:

onTouchMove: function (evt) { 
    ... 
intermediateTime = new Date(); 
    ... 
} 

Và sau đó onTouchEnd tôi nhận được một giá trị EndTime và đánh giá sự khác biệt. Nếu thời gian này là rất thấp, sau đó tôi giả sử có một "flick" ở cuối.

onTouchEnd: function (evt) { 
    ... 
var endTime = new Date(); 

var vel = (endTime - intermediateTime); 

if (vel <= 100) { 

    doMomentumOrSomething(); 

} 
    ... 
} 

Điều này rất đơn giản nhưng thực sự hoạt động khá tốt.

+0

[Trang MDN này] (https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent#touchmove) tuyên bố rằng _ "Tỷ lệ mà sự kiện touchmove được gửi là cụ thể cho từng trình duyệt, và cũng có thể thay đổi tùy thuộc vào khả năng của phần cứng của người dùng. Bạn không được dựa vào mức chi tiết cụ thể của các sự kiện này. "_ Vì bạn có vẻ đang kiểm tra thời gian delta, bạn có thể muốn xem xét điều này. – rookie1024

2

Tôi nghĩ rằng một flick sẽ được phát hiện sử dụng nhiều điểm liên quan đến vị trí và thời gian. Nếu bạn nghĩ về chuyển động của một lực cản bình thường, nó sẽ được thực hiện với tốc độ khá ổn định. Tuy nhiên, một cú đánh ở cuối cùng sẽ có vận tốc cao hơn đáng kể so với phần còn lại của kéo. Vì vậy, nếu bạn có một mảng 5 điểm, có chứa các mẫu điểm kéo cách nhau khoảng 0,1 giây (và nơi các giá trị cũ hơn trước đó trong mảng), bạn có thể tính toán vận tốc của kéo bình thường như vậy (đối với chiều dọc) kéo)

var dragVelY = (samples[2].y - samples[0].y)/3; 

sau đó, vận tốc của bộ phim tiềm năng như vậy:

var flickVelY = (samples[4].y-samples[2].y)/3; 

Nếu flickVelY lớn hơn dragVelY đáng kể, sau đó bạn đã phát hiện một flick. Tôi đã không thử nghiệm này, vì vậy bạn có thể cần phải điều chỉnh số lượng mẫu trong mảng và bao nhiêu mẫu bạn đang so sánh để có được vận tốc kéo hoặc kéo tốt. Nếu kéo dài, tôi chỉ sử dụng các phương thức Array.shift và Array.push để di chuyển các vị trí cũ ra khỏi mảng mẫu và đẩy các vị trí mới vào cuối.

Các vấn đề liên quan