2012-04-24 3 views
5

Я пытаюсь реализовать простой пользовательский метод прокрутки в своем мобильном веб-приложении. У меня проблемы с вертикальной прокруткой, где я бы хотел иметь небольшой импульс, если страница «щелкнула».Как определить «щелчок» после перетаскивания?

Проблема заключается в обнаружении жест «flick» (скорость и, возможно, длина этого жеста) после жестов перетаскивания, изменения направления, а что нет. Надеюсь, вы поймете, что я имею в виду, вы можете перетащить страницу вверх или вниз и в конце этого перетаскивания, я бы хотел определить, есть ли также щелчок.

Как вы отделите эти два? Как выглядит такая логика?

Большое спасибо за помощь.

Код: (извините, если этот отрывок немного беспорядка)

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; 


     } 

ответ

0

FYI, что я закончил делать, просто использовал время, прошедшее между onTouchMove -эвентом и onTouchEnd -эвентом.

В принципе, у меня есть переменная дата, которая постоянно переписывает себя в onTouchMove обратного вызова:

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

onTouchEnd А потом я получаю значение Конечное время и оценить разницу. Если это время очень низкое, я предполагаю, что в конце был «щелчок».

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

var vel = (endTime - intermediateTime); 

if (vel <= 100) { 

    doMomentumOrSomething(); 

} 
    ... 
} 

Это очень просто, но на самом деле работает достаточно хорошо.

+0

[Эта страница MDN] (https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent#touchmove) гласит, что _ «Скорость отправки событий touchmove зависит от браузера, и может также варьироваться в зависимости от возможностей аппаратного обеспечения пользователя. Вы не должны полагаться на определенную детализацию этих событий ». _ Поскольку вы, кажется, проверяете время дельта-времени, вы можете подумать об этом. – rookie1024

2

Я думаю, что фильм будет обнаружить с помощью нескольких точек, связанных с положением и временем. Если вы думаете о движении обычного сопротивления, это будет сделано с довольно постоянной скоростью. Однако щелчок на конце должен иметь скорость, значительно превышающую остальную часть сопротивления.

Итак, если у вас есть 5-точечный массив, содержащий образцы точек перетаскивания, расположенные на расстоянии 0,1 секунды (и где более старые значения ранее в массиве), вы могли бы рассчитать скорость нормального сопротивления так (для вертикальных перетаскивание)

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

тогда скорость потенциального взмаха так:

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

Если flickVelY значительно больше, чем dragVelY, то вы обнаружили Флик. Я не тестировал это, поэтому вам может потребоваться настроить количество выборок в массиве и количество образцов, которые вы сравниваете, чтобы получить хорошие сопротивления или скорость движения. Если это длинное перетаскивание, я бы просто использовал методы Array.shift и Array.push, чтобы переместить старые позиции из массива samples и нажать на новые в конце.

Смежные вопросы