iOS 上的 JavaScript:在不禁用滚动的情况下在 touchstart 上防止默认

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8692678/
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-08-24 07:06:23  来源:igfitidea点击:

JavaScript on iOS: preventDefault on touchstart without disabling scrolling

javascriptjqueryioseventsscroll

提问by Stefan

I am working with JavaScript and jQuery in an UIWevView on iOS.

我正在 iOS 上的 UIWevView 中使用 JavaScript 和 jQuery。

I'v added some javascript event handler that allow me to capture a touch-and-hold event to show a message when someone taps an img for some time:

我添加了一些 javascript 事件处理程序,允许我捕获触摸并保持事件以在有人点击 img 一段时间时显示消息:

$(document).ready(function() {

    var timeoutId = 0;
    var messageAppeared = false;

    $('img').on('touchstart', function(event) {

        event.preventDefault();
        timeoutId = setTimeout(function() {           

            /* Show message ... */
            messageAppeared = true;

        }, 1000);

    }).on('touchend touchcancel', function(event) {                                

        if (messageAppeared) {
            event.preventDefault();
        } else {
            clearTimeout(timeoutId);
        }
        messageAppeared = false;        
    });
});

This works well to show the message. I added the two "event.preventDefault();" lines to stop imgs inside links to trigger the link.

这可以很好地显示消息。我添加了两个“event.preventDefault();” 行停止链接内的 imgs 以触发链接。

The problem is: This also seems to prevent drag events to scroll the page from happen normally, so that the user wouldn't be able to scroll when his swipe happens to begin on an img.

问题是:这似乎也阻止了正常发生滚动页面的拖动事件,因此当用户在 img 上开始滑动时,用户将无法滚动。

How could I disable the default link action without interfering with scrolling?

如何在不干扰滚动的情况下禁用默认链接操作?

回答by Robbert

You put me on the right track Stefan, having me think the other way around. For anyone still scratching their head over this, here's my solution.

你让我走上了正确的轨道 Stefan,让我反过来思考。对于仍然为此而挠头的人,这是我的解决方案。

I was trying to allow visitors to scroll through images horizontally, without breaking vertical scrolling. But I was executing custom functionality and waiting for a vertical scroll to happen. Instead, we should allow regular behavior first and wait for a specific gesture to happen like Stefan did.

我试图让访问者水平滚动图像,而不会破坏垂直滚动。但是我正在执行自定义功能并等待发生垂直滚动。相反,我们应该首先允许常规行为,然后像 Stefan 那样等待特定的手势发生。

For example:

例如:

$("img").on("touchstart", function(e) {
    var touchStart = touchEnd = e.originalEvent.touches[0].pageX;

    var touchExceeded = false;

    $(this).on("touchmove", function(e) {
        touchEnd = e.originalEvent.touches[0].pageX;

        if(touchExceeded || touchStart - touchEnd > 50 || touchEnd - touchStart > 50) {
            e.preventDefault();

            touchExceeded = true;

            // Execute your custom function.
        }
    });

    $(this).on("touchend", function(e) {
        $(this).off("touchmove touchend");
    });
});

So basically we allow default behavior until the horizontal movement exceeds 50 pixels.

所以基本上我们允许默认行为,直到水平移动超过 50 像素。

The touchExceededvariable makes sure our function still runs if we re-enter the initial < 50 pixel area.

touchExceeded如果我们重新进入初始 < 50 像素区域,该变量确保我们的函数仍然运行。

(Note this is example code, e.originalEvent.touches[0].pageXis NOT cross browser compatible.)

(请注意,这是示例代码,e.originalEvent.touches[0].pageX不兼容跨浏览器。)

回答by Stefan

Sometimes you have to ask a question on stack overflow to find the answer yourself. There is indeed a solution to my problem, and it's as follows:

有时您必须提出有关堆栈溢出的问题才能自己找到答案。我的问题确实有解决方案,如下:

$(document).ready(function() {

    var timeoutId = 0;

    $('img').on('touchstart', function(event) {

        var imgElement = this;

        timeoutId = setTimeout(function() {           

            $(imgElement).one('click', function(event) {
                event.preventDefault();
            });

            /* Show message ... */

        }, 1000);

    }).on('touchend touchcancel', function(event) {                                
        clearTimeout(timeoutId);
    });
});

Explanation

解释

  • No preventDefault() in the touch event handlers. This brings back scrolling behavior (of course).
  • Handle a normal click event once if the message appeared, and prevent it'sdefault action.
  • 触摸事件处理程序中没有 preventDefault()。这会带回滚动行为(当然)。
  • 如果消息出现,则处理一次正常的点击事件,并阻止它的默认操作。

回答by backdesk

You could look at a gesture library like hammer.jswhich covers all of the main gesture events across devices.

您可以查看像hammer.js这样的手势库,它涵盖了跨设备的所有主要手势事件。