【问题标题】:Javascript: Any workarounds for getting Chrome for Android to fire off touchmove and touchend event listeners other than using event.preventDefault()?Javascript:除了使用 event.preventDefault() 之外,还有什么解决方法可以让 Chrome for Android 触发 touchmove 和 touchend 事件侦听器?
【发布时间】:2013-12-23 03:50:16
【问题描述】:

当使用带有 touchmove 和 touchend 事件的事件侦听器时,我无法让 Chrome for Android 确认这些事件,除非我首先使用 event.preventDefault();在代码的前面。如果我不想阻止默认滚动功能,是否可以使用其他解决方法让 Chrome for Android 确认这些事件?

示例代码:

$(document).ready(function () {
// Bind touch event listeners.
var elem = $('html').get(0);
elem.addEventListener('touchstart', function (e) { console.info('"touchstart" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchmove', function (e) { console.info('"touchmove" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchend', function (e) { console.info('"touchend" detected. Coordinates - ' + getCoord(e)); });

function getCoord(e) {
var touch = false;
if (e.touches.length > 0) {
touch = e.touches[0];
} else {
touch = e.changedTouches[0];
}
if (touch) {
return 'x: ' + touch.pageX + ', y: ' + touch.pageY;
}
}

这里的小提琴示例:http://jsfiddle.net/jQ2VS/1/

【问题讨论】:

    标签: javascript android google-chrome events


    【解决方案1】:

    如果 Google Chrome 认为用户正在平移/滚动并且您没有调用 event.preventDefault(),它会在 touchstart 之后大约 200 毫秒触发 touchcancel 事件。

    假设您想要拦截水平触摸事件并让垂直触摸事件导致平移/滚动,解决方法是:

    1. touchstart 上,将坐标存储在变量中,并将iteration 设置为0。
    2. 对于每个touchmove 事件,将iteration 设置为iteration+1。
    3. iteration 等于4(只是我发现在我的设置中可靠的“幻数”)时,计算x 轴和y 轴的总触摸偏移增量。 编辑:在移动设备上,您只会收到一个不带 event.preventDefault() 的 touchmove
    4. 如果 x 轴偏移 > y 轴偏移 * 3 则触发 event.preventDefault()。 (这样可以确保手势几乎是水平的)

    这样做的缺点是用户只能向左/向右滑动或向上/向下滚动。

    【讨论】:

    • 但是即使手指仍在屏幕上移动,touchmove 也只会触发一次或两次然后停止
    • 我发现桌面上的魔法值是 4,只有移动设备上是 1。如果您仅针对移动设备,那么如果触摸增量非常水平,那么您最好在第一次触摸移动时使用 event.preventDefault() 。这也是在 Android 的 GMail App Drawer 中观察到的行为:一旦开始滑动,就无法滚动,滚动时也无法滑动打开/关闭抽屉。
    • 太好了,昨天刚遇到同样的问题。目前 Firefox 没有应用这个规则。也许我应该查看 html 规范,看看哪个是遵循规范
    • 如果你使用webview,你需要onTouchStartCapture中的preventDefault,我花了一周的时间找到capture...
    【解决方案2】:

    最后我找到了解决方案(纯 js),即使你可能想用它来刷卡:

    var swipe = function() {
    
        var touchX, touchY, movX, movY, go;
    
        function prevent(e){
            e.preventDefault();
        }
    
        function start(e) {
            go = false;
            document.addEventListener("touchmove", prevent, false);
            touchX = e.touches[0].pageX;
            touchY = e.touches[0].pageY;
        }
    
        function move(e) {
            movX = e.touches[0].pageX - touchX;
            movY = e.touches[0].pageY - touchY;
            if(!go) {
                (Math.abs(movY) < Math.abs(movX)) ? go = true : stop(e);
            } else {
                /* *************** */
                // cast your spell
                /* *************** */
            }
        }
    
        function stop(e) {
            document.removeEventListener("touchmove", prevent, false);
        }
    
        document.addEventListener("touchstart", start, true);
        document.addEventListener("touchmove", move, true);
        document.addEventListener("touchend", stop, true);
        document.addEventListener("touchleave", stop, true);
        document.addEventListener("touchcancel", stop, true);
    
    }
    

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      最简单的答案是你必须在第一个 touchmove 事件上阻止默认,否则它们将被取消。

      【讨论】:

      • 我知道 preventDefault 会有所帮助。不过,正如我上面所问的,我正在寻找一种不使用 preventDefault 的解决方案,因为在这种情况下我不想破坏滚动功能。
      • 我知道。但答案是,如果你想获取 html 元素上的所有触摸事件,你必须阻止默认:/。
      • 这根本不能回答问题。这不是一个“简单的答案”。建议放弃寻找答案。
      【解决方案4】:

      我发现阻止触摸取消工作正常。

      【讨论】:

      • 如果您有一个适合您的示例,请考虑发布一些代码来帮助支持您的回答。
      【解决方案5】:

      接受的答案不正确。

      在 Android 上,如果在 touchstart 上未设置 preventDefault,则设备假定本机滚动并且不再向 webview 发送触摸事件。如果设置了 preventDefault,则所有本机滚动都将被禁用。

      这里有一个 shim 提供带有原生滚动的滑动事件:https://github.com/TNT-RoX/android-swipe-shim

      【讨论】:

        猜你喜欢
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-24
        • 1970-01-01
        相关资源
        最近更新 更多