使用纯JavaScript捕获“tap”事件

49

如何使用纯JS捕获用户的“tap”事件?不幸的是,我不能使用任何库。


@DanOvidiuBoncut 没有什么需要道歉的。 - Michael
注释:已注释 不要;;' - Ashton Drye
评论:已评论 不要;;' - undefined
5个回答

51

click事件在鼠标点击和触摸屏幕时触发。

touchstart事件在屏幕被触摸时触发。

touchend事件在触摸结束时触发。如果默认操作被阻止,则不会触发click事件。

http://www.w3.org/TR/touch-events/


@DineshKumarDJ 随意将一些示例代码作为单独的答案发布。在另一个答案下发表评论并不是一个好地方,因为人们无法判断您的建议的质量。 - John Dvorak
@JohnDvorak 确定已删除该评论,将作为单独的答案添加。 - Dinesh Kumar DJ
我们注意到在Safari移动版中,当点击元素时,单击事件不会触发。对我们来说,touchend是有效的,但单击事件从未触发。 - SubliemeSiem
由于这并没有提及持续时间,我不认为它回答了关于触摸事件的问题。 - geotheory

8

touchstart, touchend 和其他事件。您可以通过以下方式为它们添加事件监听器:

var el = document.getElementById('test');
el.addEventListener('touchstart', touchHandler);

您可以在MDN网站上找到更多关于原生DOM事件的信息。


7
这不是我的代码,但我记不得从哪里得到它,成功使用过。它使用jQuery,但没有额外的库或插件来处理触摸操作本身。
$.event.special.tap = {
    setup: function(data, namespaces) {
        var $elem = $(this);
        $elem.bind('touchstart', $.event.special.tap.handler)
             .bind('touchmove', $.event.special.tap.handler)
             .bind('touchend', $.event.special.tap.handler);
    },

    teardown: function(namespaces) {
        var $elem = $(this);
        $elem.unbind('touchstart', $.event.special.tap.handler)
             .unbind('touchmove', $.event.special.tap.handler)
             .unbind('touchend', $.event.special.tap.handler);
    },

    handler: function(event) {
        event.preventDefault();
        var $elem = $(this);
        $elem.data(event.type, 1);
        if (event.type === 'touchend' && !$elem.data('touchmove')) {
            event.type = 'tap';
            $.event.handle.apply(this, arguments);
        } else if ($elem.data('touchend')) {
            $elem.removeData('touchstart touchmove touchend');
        }
    }
};

$('.thumb img').bind('tap', function() {
    //bind tap event to an img tag with the class thumb
}

我曾将此用于一项专门针对iPad的项目,因此可能需要进行调整才能同时适用于桌面和平板电脑。


1
这段代码还可以规避使用常规点击处理程序时出现的触控延迟。 - Kayo
15
这不是纯JS,正如你所指出的那样,因此它并不能回答这个问题。 - Derek Henderson
1
@Derek 是的,但这对其他人也很有用。 - Maya
4
@NieDzejkob,这不是对这个问题有用的答案。使用jQuery或其他库很容易找到解决方案,但有时开发人员会受到限制,无法使用库,这就是为什么OP指定了“纯JavaScript”的原因。如果您想在评论中指出jQuery答案,就像Dinesh上面所做的那样,那是可以的。 - Derek Henderson

4

我自己写了一个小脚本,虽然不是纯JS,但对我来说工作得很好。 它可以防止在滚动时执行脚本,这意味着脚本仅在“轻触”事件上触发。

$(element)
        .on('touchstart', function () {
            $(this).data('moved', '0');
        })
        .on('touchmove', function () {
            $(this).data('moved', '1');
        })
        .on('touchend', function () {
            if($(this).data('moved') == 0){
                // HERE YOUR CODE TO EXECUTE ON TAP-EVENT
            }
        });

13
问题很清楚,关于“纯JS”和“我不能使用任何库”。 - Byscripts

0
我知道这是一个老问题,但是我仍然没有看到任何全面的纯JS解决方案,所以这是基于这个帖子中其他人非常有价值的信息的解决方案。
const onClickOrTap = (element, handler) => {
  let touchMoveHappened = false
  element.addEventListener('touchstart', () => {
    // on mobile this is the 1st event that happens
    touchMoveHappened = false
  })
  element.addEventListener('touchmove', () => {
    // on mobile this might get triggered in which case the
    // click or tap will get cancelled
    // we'll keep a track of it
    touchMoveHappened = true
  })
  element.addEventListener('touchend', (e) => {
    // happens after touchstart, but before click
    // if touch happened then we'll exit
    if (touchMoveHappened) {
      return
    }
    // calling preventDefault() will make sure the
    // subsequent click will not get triggered
    e.preventDefault()
    // at this point we are ready to call our original handler
    handler(e)
  })
  element.addEventListener('click', () => {
    // this will only get triggered on desktop
    // because we call e.preventDefault in "touchend"
    handler(e)
  })
}

const btn = document.querySelector('button')
onClickOrTap(btn, (e) => {
  // will get triggered when the btn is clicked
  // or tapped, but not when scrolling on mobile
})

对于使用TypeScript的人来说:
declare const onClickOrTap: (element: Element, fn: (e: Event | MouseEvent<Element, globalThis.MouseEvent>) => void) => void

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接