javascript 如何为移动设备实现滑动手势?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15084675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:26:18  来源:igfitidea点击:

How to implement swipe gestures for mobile devices?

javascriptmobiletouchswipegestures

提问by fotuzlab

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

我有一个用 AngularJS 制作的应用程序,它有箭头键导航来切换视图。

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

我想使用轻扫触摸设备来实现此导航。我试过jGestures库,但它不适合刷卡。我被建议不要使用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).

编辑:它没有干净地检测到滑动。我在多种设备上对其进行了测试,包括 iPad,它需要多次滑动才能执行操作(在我的情况下是路由)。

回答by EscapeNetscape

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).

如果检测到滑动,则使用参数 element-id 和“l,r,u,d”(左、右、上、下)调用函数“myfunction”。

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

示例:http: //jsfiddle.net/rvuayqeo/1/



I (UlysseBN) made a new version of this scriptbased 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.

我 (UlysseBN)基于这个脚本制作了一个新版本,它使用了更现代的 JavaScript,看起来它在某些情况下表现更好。如果您认为它应该是对这个答案的编辑,请告诉我,如果您是原作者并且最终进行了编辑,我将删除我的答案。

回答by Jorik

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

你试过 Hammerjs 吗?它通过使用触摸速度支持滑动手势。 http://eightmedia.github.com/hammer.js/

回答by Pixelomo

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;                                             
};

回答by vsp

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

还有一个名为 angular-gestures 的 AngularJS 模块,它基于hammer.js:https: //github.com/wzr1337/angular-gestures

回答by BenM

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

我知道无耻的插件,但你可能想考虑我写的一个 jQuery 插件:

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

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

It does not require jQuery Mobile, only jQuery.

它不需要 jQuery Mobile,只需要 jQuery。

回答by Ulysse BN

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...

注意:受到EscapeNetscape 的回答的极大启发,我在评论中使用现代 javascript 对他的脚本进行了编辑。由于用户的兴趣和大量的 4 小时 jsfiddle.net 停机时间,我对此做出了回答。我选择不编辑原始答案,因为它会改变一切......



Here is a detectSwipefunction, 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.

这是一个detectSwipe功能,运行良好(在我的一个网站上使用)。我建议你在使用之前阅读它。随意查看/编辑答案。

// 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>

回答by Konrad Holl

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 myfunctionis called with parameter element-id and 'left', 'right', 'up'oder 'down'.

如果检测到滑动,则myfunction使用参数 element-id 和'left', 'right', 'up'oder调用该函数'down'

回答by Star

Hammer time!

锤子时间!

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

我使用过 Hammer JS,它可以与手势配合使用。从这里阅读详细信息: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.

好在它比 jQuery mobile 轻得多,速度也快得多。您也可以在他们的网站上进行测试。

回答by elixon

I looked at several solutions but all failed with scroll and select text being the biggest confusion. Instead of scrolling right I was closing boxes and such.

我查看了几个解决方案,但都失败了,滚动和选择文本是最大的困惑。我没有向右滚动,而是关闭框等。

I just finished my implementation that does it all for me.

我刚刚完成了为我完成所有工作的实现。

https://github.com/webdevelopers-eu/jquery-dna-gestures

https://github.com/webdevelopers-eu/jquery-dna-gestures

It is MIT so do what you want - and yes, it is really simple - 800 bytes minified. You can check it out on my (under-development) site https://cyrex.tech- swiperight on touch-devices should dismiss popup windows.

这是麻省理工学院,所以做你想做的 - 是的,这真的很简单 - 800 字节缩小。您可以在我的(正在开发的)网站https://cyrex.tech 上查看 - 触摸设备上的 swiperight 应该关闭弹出窗口。