javascripttouchmove

Trigger JS function only when tap ends


I made a lightbox that runs on Javascript and I recently added a function where swiping left or right on mobile changes the image that appears. However, the code I'm using triggers the function every time my finger moves a few pixels. I want the function to trigger exactly one when I swipe once, no matter the length of the swipe. Here's my current code:

/* Defining plusSlides function */

function plusSlides(n) {
  showSlides(slideIndex += n);
}


/* The code for swiping */

document.addEventListener('touchstart', handleTouchStart, false);        
document.addEventListener('touchmove', handleTouchMove, false);

var xDown = null;                                                        
var yDown = null;

function getTouches(evt) {
  return evt.touches ||             // browser API
         evt.originalEvent.touches; // jQuery
}                                                     
                                                                         
function handleTouchStart(evt) {
    const firstTouch = getTouches(evt)[0];                                      
    xDown = firstTouch.clientX;                                      
    yDown = firstTouch.clientY;                                      
};                                                
                                                                         
function handleTouchMove(evt) {
    if ( ! xDown || ! yDown ) {
        return;
    }

    var xUp = evt.touches[0].clientX;                                    
    var yUp = evt.touches[0].clientY;

    var xDiff = xDown - xUp;
    var yDiff = yDown - yUp;
                                                                         
    if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
        if ( xDiff > 0 ) {
            plusSlides(1)
        } else {
            plusSlides(-1)
        }
    }
    /* reset values */
    xDown = null;
    yDown = null;                                             
};

Solution

  • You could use the touchend event and split the handleTouchMove handler in two handlers (+f.e. handleTouchEnd). For that you need to define xDiff and yDiff globally.

    /* Defining plusSlides function */
    
    function plusSlides(n) {
      showSlides(slideIndex += n);
    }
    
    
    /* The code for swiping */
    
    document.addEventListener('touchstart', handleTouchStart, false);        
    document.addEventListener('touchmove', handleTouchMove, false);      
    document.addEventListener('touchend', handleTouchEnd, false);
    
    var xDown = null;                                                        
    var yDown = null;
    var xDiff = null;         // DEFINED GLOBALLY                                               
    var yDiff = null;
    
    function getTouches(evt) {
      return evt.touches ||             // browser API
             evt.originalEvent.touches; // jQuery
    }                                                     
                                                                             
    function handleTouchStart(evt) {
        const firstTouch = getTouches(evt)[0];                                      
        xDown = firstTouch.clientX;                                      
        yDown = firstTouch.clientY;                                      
    };                                                
                                                                             
    function handleTouchMove(evt) {
        if ( ! xDown || ! yDown ) {
            return;
        }
    
        var xUp = evt.touches[0].clientX;                                    
        var yUp = evt.touches[0].clientY;
    
        xDiff = xDown - xUp;
        yDiff = yDown - yUp;
    }
    
    function handleTouchEnd() {                                                  
        if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
            if ( xDiff > 0 ) {
                plusSlides(1)
            } else {
                plusSlides(-1)
            }
        }
        /* reset values */
        xDown = null;
        yDown = null;                                             
    };