触摸事件是否包括clientX / Y滚动?

11

我正在尝试从触摸事件(例如 touchstart)中获取相对于浏览器视口的触摸坐标。我尝试使用 clientX/Y 属性来获取它们,但这两个属性实际上返回包括滚动值在内的坐标。

这与规范不符,因为规范规定 clientX/Y 应该返回没有滚动的坐标。

  • 我尝试添加/删除 meta viewport 标记 - 但没有成功。
  • 我在 iPhone 上的 iOS 4.3 和 Fennec nightly 中进行了测试 - 都返回带有滚动值的坐标。

我做错了什么?

谢谢

2个回答

15

你没有做错任何事情。这是在旧版本的webkit中发生的一个bug,当页面被滚动时会出现这个问题。我曾经在iOS4中见过这个bug,还有一个不同的bug在Android 4.0中。

我找到了一种方法来检测这些bug并计算正确的值。希望这对其他人有用:

function fixTouch (touch) {
    var winPageX = window.pageXOffset,
        winPageY = window.pageYOffset,
        x = touch.clientX,
        y = touch.clientY;

    if (touch.pageY === 0 && Math.floor(y) > Math.floor(touch.pageY) ||
        touch.pageX === 0 && Math.floor(x) > Math.floor(touch.pageX)) {
        // iOS4 clientX/clientY have the value that should have been
        // in pageX/pageY. While pageX/page/ have the value 0
        x = x - winPageX;
        y = y - winPageY;
    } else if (y < (touch.pageY - winPageY) || x < (touch.pageX - winPageX) ) {
        // Some Android browsers have totally bogus values for clientX/Y
        // when scrolling/zooming a page. Detectable since clientX/clientY
        // should never be smaller than pageX/pageY minus page scroll
        x = touch.pageX - winPageX;
        y = touch.pageY - winPageY;
    }

    return {
        clientX:    x,
        clientY:    y
    };
}

这个函数必须针对事件.touches数组中的每个触摸点进行调用。


10

试试这个

event.touches[0].pageX

请注意,即使您像这样定义事件(在此处使用jquery),它始终是event.touches。

$("body").bind('touchmove', function(e){ 
//stops normal scrolling with touch
e.preventDefault();

console.log(event.touches[0].pageX)

})

Safari指南提供了更多细节。


是的,我正在通过event.touches[0].clientX检索它...但我仍然不知道为什么(至少在iOS上)报告pageX和clientX相同(实际上它们应该因视口偏移而有所不同)。 - kuvik
1
你是对的,似乎有个 bug。你可以通过调整页面滚动来规避它(使用(event.targetTouches[0].screenY - $(window).scrollTop()))。 - Thomas Brasington
e.originalEvent.touches[0].clientY 对我起作用 - Wasim A.

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