How to implement swipe gestures for mobile devices?

a 夏天 提交于 2019-12-17 23:49:12

问题


I have an application made in AngularJS which has arrow key navigation to switch views.

I want to implement this navigation using swipe for touch devices. I tried jGestures library but it doesn't go well with swipe. I have been recommended NOT to use jquery mobile.

Is there any other way to implement swipe?

EDIT: It does not detect swipe cleanly. I tested it on multiple devices, including iPad and it takes multiple swipes to do an action(routing in my case).


回答1:


I made this function for my needs.

Feel free to use it. Works great on mobile devices.

function detectswipe(el,func) {
  swipe_det = new Object();
  swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0;
  var min_x = 30;  //min x swipe for horizontal swipe
  var max_x = 30;  //max x difference for vertical swipe
  var min_y = 50;  //min y swipe for vertical swipe
  var max_y = 60;  //max y difference for horizontal swipe
  var direc = "";
  ele = document.getElementById(el);
  ele.addEventListener('touchstart',function(e){
    var t = e.touches[0];
    swipe_det.sX = t.screenX; 
    swipe_det.sY = t.screenY;
  },false);
  ele.addEventListener('touchmove',function(e){
    e.preventDefault();
    var t = e.touches[0];
    swipe_det.eX = t.screenX; 
    swipe_det.eY = t.screenY;    
  },false);
  ele.addEventListener('touchend',function(e){
    //horizontal detection
    if ((((swipe_det.eX - min_x > swipe_det.sX) || (swipe_det.eX + min_x < swipe_det.sX)) && ((swipe_det.eY < swipe_det.sY + max_y) && (swipe_det.sY > swipe_det.eY - max_y) && (swipe_det.eX > 0)))) {
      if(swipe_det.eX > swipe_det.sX) direc = "r";
      else direc = "l";
    }
    //vertical detection
    else if ((((swipe_det.eY - min_y > swipe_det.sY) || (swipe_det.eY + min_y < swipe_det.sY)) && ((swipe_det.eX < swipe_det.sX + max_x) && (swipe_det.sX > swipe_det.eX - max_x) && (swipe_det.eY > 0)))) {
      if(swipe_det.eY > swipe_det.sY) direc = "d";
      else direc = "u";
    }

    if (direc != "") {
      if(typeof func == 'function') func(el,direc);
    }
    direc = "";
    swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0;
  },false);  
}

function myfunction(el,d) {
  alert("you swiped on element with id '"+el+"' to "+d+" direction");
}

To use the function just use it like

detectswipe('an_element_id',myfunction);

detectswipe('an_other_element_id',my_other_function);

If a swipe is detected the function "myfunction" is called with parameter element-id and "l,r,u,d" (left,right,up,down).

Example: http://jsfiddle.net/rvuayqeo/1/


I (UlysseBN) made a new version of this script based on this one which use more modern JavaScript, it looks like it behaves better on some cases. If you think it should rather be an edit of this answer let me know, if you are the original author and you end up editing, I'll delete my answer.




回答2:


Have you tried Hammerjs? It supports swipe gestures by using the velocity of the touch. http://eightmedia.github.com/hammer.js/




回答3:


The simplest solution I've found that doesn't require a plugin:

document.addEventListener('touchstart', handleTouchStart, false);        
document.addEventListener('touchmove', handleTouchMove, false);
var xDown = null;                                                        
var yDown = null;  

function handleTouchStart(evt) {                                         
    xDown = evt.touches[0].clientX;                                      
    yDown = evt.touches[0].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 ) {
        /* left swipe */ 
        } else {
        /* right swipe */
        }                       
    } else {
        if ( yDiff > 0 ) {
        /* up swipe */ 
        } else { 
        /* down swipe */
        }                                                                 
    }
    /* reset values */
    xDown = null;
    yDown = null;                                             
};



回答4:


There is also an AngularJS module called angular-gestures which is based on hammer.js: https://github.com/wzr1337/angular-gestures




回答5:


Shameless plug I know, but you might want to consider a jQuery plugin that I wrote:

https://github.com/benmajor/jQuery-Mobile-Events

It does not require jQuery Mobile, only jQuery.




回答6:


I like your solution and implemented it on my site - however, with some little improvements. Just wanted to share my code:

function detectSwipe(id, f) {
    var detect = {
        startX: 0,
        startY: 0,
        endX: 0,
        endY: 0,
        minX: 30,   // min X swipe for horizontal swipe
        maxX: 30,   // max X difference for vertical swipe
        minY: 50,   // min Y swipe for vertial swipe
        maxY: 60    // max Y difference for horizontal swipe
    },
        direction = null,
        element = document.getElementById(id);

    element.addEventListener('touchstart', function (event) {
        var touch = event.touches[0];
        detect.startX = touch.screenX;
        detect.startY = touch.screenY;
    });

    element.addEventListener('touchmove', function (event) {
        event.preventDefault();
        var touch = event.touches[0];
        detect.endX = touch.screenX;
        detect.endY = touch.screenY;
    });

    element.addEventListener('touchend', function (event) {
        if (
            // Horizontal move.
            (Math.abs(detect.endX - detect.startX) > detect.minX)
                && (Math.abs(detect.endY - detect.startY) < detect.maxY)
        ) {
            direction = (detect.endX > detect.startX) ? 'right' : 'left';
        } else if (
            // Vertical move.
            (Math.abs(detect.endY - detect.startY) > detect.minY)
                && (Math.abs(detect.endX - detect.startX) < detect.maxX)
        ) {
            direction = (detect.endY > detect.startY) ? 'down' : 'up';
        }

        if ((direction !== null) && (typeof f === 'function')) {
            f(element, direction);
        }
    });
}

Use it like:

detectSwipe('an_element_id', myfunction);

Or

detectSwipe('another_element_id', my_other_function);

If a swipe is detected the function myfunction is called with parameter element-id and 'left', 'right', 'up' oder 'down'.




回答7:


Hammer time!

I have used Hammer JS and it work with gesture. Read details from here: https://hammerjs.github.io/

Good thing that it is much more light weight and fast then jQuery mobile. You can test it on their website as well.




回答8:


NOTE: Greatly inspired by EscapeNetscape's answer, I've made an edit of his script using modern javascript in a comment. I made an answer of this due to user interest and a massive 4h jsfiddle.net downtime. I chose not to edit the original answer since it would change everything...


Here is a detectSwipe function, working pretty well (used on one of my websites). I'd suggest you read it before you use it. Feel free to review it/edit the answer.

// usage example
detectSwipe('swipeme', (el, dir) => alert(`you swiped on element with id ${el.id} to ${dir} direction`))

// source code

// Tune deltaMin according to your needs. Near 0 it will almost
// always trigger, with a big value it can never trigger.
function detectSwipe(id, func, deltaMin = 90) {
  const swipe_det = {
    sX: 0,
    sY: 0,
    eX: 0,
    eY: 0
  }
  // Directions enumeration
  const directions = Object.freeze({
    UP: 'up',
    DOWN: 'down',
    RIGHT: 'right',
    LEFT: 'left'
  })
  let direction = null
  const el = document.getElementById(id)
  el.addEventListener('touchstart', function(e) {
    const t = e.touches[0]
    swipe_det.sX = t.screenX
    swipe_det.sY = t.screenY
  }, false)
  el.addEventListener('touchmove', function(e) {
    // Prevent default will stop user from scrolling, use with care
    // e.preventDefault();
    const t = e.touches[0]
    swipe_det.eX = t.screenX
    swipe_det.eY = t.screenY
  }, false)
  el.addEventListener('touchend', function(e) {
    const deltaX = swipe_det.eX - swipe_det.sX
    const deltaY = swipe_det.eY - swipe_det.sY
    // Min swipe distance, you could use absolute value rather
    // than square. It just felt better for personnal use
    if (deltaX ** 2 + deltaY ** 2 < deltaMin ** 2) return
    // horizontal
    if (deltaY === 0 || Math.abs(deltaX / deltaY) > 1)
      direction = deltaX > 0 ? directions.RIGHT : directions.LEFT
    else // vertical
      direction = deltaY > 0 ? directions.UP : directions.DOWN

    if (direction && typeof func === 'function') func(el, direction)

    direction = null
  }, false)
}
#swipeme {
  width: 100%;
  height: 100%;
  background-color: orange;
  color: black;
  text-align: center;
  padding-top: 20%;
  padding-bottom: 20%;
}
<div id='swipeme'>
  swipe me
</div>


来源:https://stackoverflow.com/questions/15084675/how-to-implement-swipe-gestures-for-mobile-devices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!