在 iPhone 和 Android 上通过 JavaScript 检测手指滑动

IT技术 javascript iphone android swipe
2021-02-01 08:58:45

您如何使用 JavaScript 检测到用户在网页上向某个方向滑动手指?

我想知道是否有一种解决方案适用于 iPhone 和 Android 手机上的网站。

6个回答

简单的香草 JS 代码示例:

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 ) {
            /* right swipe */ 
        } else {
            /* left swipe */
        }                       
    } else {
        if ( yDiff > 0 ) {
            /* down swipe */ 
        } else { 
            /* up swipe */
        }                                                                 
    }
    /* reset values */
    xDown = null;
    yDown = null;                                             
};

在安卓中测试。

这很好用,但左/右和上/下是向后的。
2021-03-16 08:58:45
它工作得很好,但在检测直线运动时有问题。我将在此主题上发布另一个答案,将其修复为 JQuery(桌面)解决方案。它还添加了这些滑动事件的鼠标版本并添加了灵敏度选项。
2021-03-23 08:58:45
originalEvent 是一个 JQuery 属性。如果你在没有 JQuery 的情况下运行纯 javascript,它应该被排除在外。如果在没有 JQuery 的情况下运行,当前代码会引发异常。
2021-03-28 08:58:45
看起来很酷很简单,不知道对这个事件的支持是什么 touchstarttouchmove
2021-04-03 08:58:45
该死。主题已关闭,因此无法添加我的答案!
2021-04-03 08:58:45

我将这里的一些答案合并到一个脚本中,该脚本使用CustomEvent在 DOM 中触发滑动事件。在0.7K添加刷卡,events.min.js脚本到你的页面和监听刷卡事件:

刷过

document.addEventListener('swiped', function(e) {
    console.log(e.target); // the element that was swiped
    console.log(e.detail.dir); // swiped direction
});

向左滑动

document.addEventListener('swiped-left', function(e) {
    console.log(e.target); // the element that was swiped
});

向右滑动

document.addEventListener('swiped-right', function(e) {
    console.log(e.target); // the element that was swiped
});

向上滑动

document.addEventListener('swiped-up', function(e) {
    console.log(e.target); // the element that was swiped
});

向下滑动

document.addEventListener('swiped-down', function(e) {
    console.log(e.target); // the element that was swiped
});

您还可以直接附加到元素:

document.getElementById('myBox').addEventListener('swiped-down', function(e) {
    console.log(e.target); // the element that was swiped
});

可选配置

您可以指定以下属性来调整页面中的滑动交互功能(这些是可选的)

<div data-swipe-threshold="10"
     data-swipe-timeout="1000"
     data-swipe-ignore="false">
      Swiper, get swiping!
</div>

要在应用程序范围内设置默认值,请在最顶层元素上设置配置属性:

<body data-swipe-threshold="100" data-swipe-timeout="250">
    <div>Swipe me</div>
    <div>or me</div>
</body>

源代码可在Github 上找到

我来到这里是因为纯刷卡对我来说在 MOBILE 上不起作用
2021-03-12 08:58:45
@StefanBob 如果你在github repo打勾并提供足够的信息让我重现这个问题,我会调查一下
2021-03-24 08:58:45
谢谢,它完美地工作!我用你的库替换了 Hammer.js,因为前者不适用于浏览器缩放,这是一个严重的可用性问题。使用这个库,缩放可以正常工作(在 Android 上测试)
2021-03-25 08:58:45
Hammer.js 似乎不再维护
2021-04-03 08:58:45

用于水平滑动的简单香草 JS 示例:

let touchstartX = 0
let touchendX = 0

const slider = document.getElementById('slider')

function handleGesture() {
  if (touchendX < touchstartX) alert('swiped left!')
  if (touchendX > touchstartX) alert('swiped right!')
}

slider.addEventListener('touchstart', e => {
  touchstartX = e.changedTouches[0].screenX
})

slider.addEventListener('touchend', e => {
  touchendX = e.changedTouches[0].screenX
  handleGesture()
})

您可以对垂直滑动使用完全相同的逻辑。

@MattiaRasulo 可能需要添加上下滑动
2021-03-15 08:58:45
大声笑,这太简单了,甚至可以指定“旅行距离”。
2021-03-26 08:58:45
到目前为止最好的答案..很遗憾它没有更多的赞成..
2021-03-28 08:58:45

根据@givanse 的回答,您可以这样做classes

class Swipe {
    constructor(element) {
        this.xDown = null;
        this.yDown = null;
        this.element = typeof(element) === 'string' ? document.querySelector(element) : element;

        this.element.addEventListener('touchstart', function(evt) {
            this.xDown = evt.touches[0].clientX;
            this.yDown = evt.touches[0].clientY;
        }.bind(this), false);

    }

    onLeft(callback) {
        this.onLeft = callback;

        return this;
    }

    onRight(callback) {
        this.onRight = callback;

        return this;
    }

    onUp(callback) {
        this.onUp = callback;

        return this;
    }

    onDown(callback) {
        this.onDown = callback;

        return this;
    }

    handleTouchMove(evt) {
        if ( ! this.xDown || ! this.yDown ) {
            return;
        }

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

        this.xDiff = this.xDown - xUp;
        this.yDiff = this.yDown - yUp;

        if ( Math.abs( this.xDiff ) > Math.abs( this.yDiff ) ) { // Most significant.
            if ( this.xDiff > 0 ) {
                this.onLeft();
            } else {
                this.onRight();
            }
        } else {
            if ( this.yDiff > 0 ) {
                this.onUp();
            } else {
                this.onDown();
            }
        }

        // Reset values.
        this.xDown = null;
        this.yDown = null;
    }

    run() {
        this.element.addEventListener('touchmove', function(evt) {
            this.handleTouchMove(evt).bind(this);
        }.bind(this), false);
    }
}

你可以像这样使用它:

// Use class to get element by string.
var swiper = new Swipe('#my-element');
swiper.onLeft(function() { alert('You swiped left.') });
swiper.run();

// Get the element yourself.
var swiper = new Swipe(document.getElementById('#my-element'));
swiper.onLeft(function() { alert('You swiped left.') });
swiper.run();

// One-liner.
(new Swipe('#my-element')).onLeft(function() { alert('You swiped left.') }).run();
这段代码可能无法工作,因为您在尝试调用.bindundefined时会遇到异常,因为您handleTouchMove实际上没有返回任何内容。在调用函数时调用 bind 也是没用的,this.因为它已经绑定到当前上下文
2021-03-12 08:58:45
如果您想等到滑动结束(意思是在他们抬起手指或 onmouseup 之后),请更改touches[0]changedTouches[0]并且事件处理程序类型handleTouchMovehandleTouchEnd
2021-03-15 08:58:45
我刚刚删除.bind(this);,它运行得很好。谢谢@nicholas_r
2021-03-20 08:58:45
调用run()两次,你会得到一个令人讨厌的内存泄漏
2021-03-28 08:58:45
部分自己获取元素我只是删除了 document.getElementById('my-element') 中的 '#' 并且效果很好。谢谢@Marwelln :)
2021-04-06 08:58:45

我之前使用的是您必须检测 mousedown 事件,记录其 x,y 位置(以相关的为准),然后检测 mouseup 事件,并减去这两个值。

我相信可以使用的是 touchstart、touchmove、touchcancel 和 touchend,而不是 mousedown 或 mouseup。
2021-04-09 08:58:45