jQuery(滑动与触摸)pageX 和 pageY 不断返回 0

发布于 2024-11-30 01:10:51 字数 1483 浏览 5 评论 0原文

我正在 iPhone 上玩 touchstart 和 touchend 事件。我构建了一个示例页面,其中包含 div,如果您触摸它并滚动页面,它应该返回开始位置和结束位置的 y 坐标。

链接: http://jsbin.com/ibemom/2

jQuery:

var touchStartPos;

$('.theDiv')
  .bind('touchstart', function(e){
    touchStartPos = e.pageY;
  })
  .bind('touchend', function(e){
    alert(touchStartPos + ' | ' + e.pageY)
  })   

当我在我的页面上加载该页面时然而,iPhone 上的警报始终将这两个值报告为零。有人看到我的东西有什么问题吗?

更新:

我在 jQuery Mobile 项目中偶然发现了这段代码:https://github。 com/jquery/jquery-mobile/issues/734

它的评论很突出:

 // (in iOS event.pageX and event.pageY are always 0 )

它没有说为什么是这样的,但至少我发现其他人看到了同样的事情。将深入研究该页面上的示例代码,看看是否有解决方案。

更新二:

好吧,在查看上面链接中的示例代码后,看起来这将返回一个实际值:

e.originalEvent.touches[0].pageY

问题是,我现在意识到这并不完全是我需要的。它返回我在将事件附加到的对象中触摸的区域的 Y 偏移量(与 HTML 文档相关)...而不是浏览器窗口。

我的目标是找出触摸在屏幕上的开始位置和结束位置......然后比较这些值。如果它们有很大不同,那么我们假设执行了滑动......而不是触摸。

更新三:

我还找到了对这些示例的引用:

e.originalEvent.touches[0].pageX

event.targetTouches[0].pageY

尽管我似乎也无法让它们发挥作用。两者都返回未定义的错误。

更新四:

看起来一种解决方案是跟踪文档本身的 offset() 。我可以将 touchend 事件应用于文档,然后检查它的偏移量。

问题是我的 touchend 事件将首先在我的页面上的元素上触发,然后它会在文档上触发它(冒泡)。因此,在我需要弄清楚如何处理对象 touchend 事件之前,我实际上无法确定它是触摸还是滑动。

还在思考这个...

I'm playing with touchstart and touchend events on my iPhone. I built a sample page that has div that if you touch it and scroll the page, it should return the y coordinates of the start and end positions.

link: http://jsbin.com/ibemom/2

the jQuery:

var touchStartPos;

$('.theDiv')
  .bind('touchstart', function(e){
    touchStartPos = e.pageY;
  })
  .bind('touchend', function(e){
    alert(touchStartPos + ' | ' + e.pageY)
  })   

When I load that page on my iPhone, however, the alert keeps reporting both values as zero. Anyone see anything wrong with what I have?

UPDATE:

I stumbled across this bit of code in the jQuery Mobile project: https://github.com/jquery/jquery-mobile/issues/734

A comment it from it stuck out:

 // (in iOS event.pageX and event.pageY are always 0 )

It doesn't say why that's the case, but at least I found someone else that sees the same thing. Will dig through the sample code on that page to see if the solution is there.

UPDATE II:

Well, after looking through the sample code in the link above, it looks like this will return an actual value:

e.originalEvent.touches[0].pageY

The catch is, I now realize that's not quite I need. It's returning the Y offset of the area I touched within the object I attached the event to IN RELATION TO THE HTML DOCUMENT...rather than the browser window.

My goal is to figure out where on the screen the touch started, and where it ended...and then compare the values. If they are quite a bit different, then we assue a swipe was performed...rather than a touch.

UPDATE III:

I'm also finding references to these examples:

e.originalEvent.touches[0].pageX

event.targetTouches[0].pageY

Though I can't seem to get those to work either. Both return undefined errors.

UPDATE IV:

It looks like one solution is to track offset() on the document itself. I can apply a touchend event to the document, and then check it's offset.

The problem with this is that my touchend event will first trigger on the element on my page and THEN it'll fire it on the document (bubbling). So I can't actually determine if it was a touch or swipe BEFORE I need to figure out what to do on the objects touchend event.

Still pondering this one...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

豆芽 2024-12-07 01:10:51

好吧,简单的回答是,当手指离开屏幕时,您无法检测到触摸(touchend)。

我的第一个示例证明: http://jsfiddle.net/Y4fHD/

现在来解决方法。或者随心所欲地称呼它。也许不检测 touchend 事件是有意义的,因为触摸结束。

touchmove 事件上绑定处理程序:http://jsfiddle.net/Y4fHD/1/

var endCoords = {};
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

然后使用变量 endCoords 来确定最后一次触摸

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

好吧,尝试点击您的设备!那么错误仍然会发生:为什么?因为你还没有动过你的触碰。

如果我们都准备好在 touchstart 中定义 endCoords 变量,我们就在那里:http: //jsfiddle.net/Y4fHD/2/

var endCoords = {};
$(document.body).bind("touchstart touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

然后使用变量 endCoords 来确定最后一次触摸

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

现在尝试点击您的设备!

最后的一些注意事项是:创建变量:startCoordsendCoords,然后在touchend事件中使用它们:http://jsfiddle.net/Y4fHD/3/

var startCoords = {}, endCoords = {};
$(document.body).bind("touchstart", function(event) {
    startCoords = endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchend", function(event) {
    $('p').text("Your touch on the axis: " + Math.abs(startCoords.pageX-endCoords.pageX) + "x, " + Math.abs(startCoords.pageY-endCoords.pageY) + "y");
});

注意:
上面的例子都没有经过测试,希望它能起作用!
Math.abs 给出数字的绝对值,例如:-5 变为 5

Ok the quick answer is you can't detect a touch when the finger leaves the screen (touchend).

My first example proves that: http://jsfiddle.net/Y4fHD/

Now to the workaround. Or call it what you want. Maybe it makes sense not detection on the touchend event because the the touch has ended.

Bind the handler on the touchmove event: http://jsfiddle.net/Y4fHD/1/

var endCoords = {};
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

And then use the variable endCoords to determinate the last touch

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

Ok try to just tap your device! Then the error still will ocure: Why? Because you havn't moved your touch.

If we all ready in the touchstart defines the endCoords variable we are there: http://jsfiddle.net/Y4fHD/2/

var endCoords = {};
$(document.body).bind("touchstart touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

And then use the variable endCoords to determinate the last touch

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

Now try to tap your device!

Some final notes will be: Make to variables: startCoords and endCoords then use these in the touchend event: http://jsfiddle.net/Y4fHD/3/

var startCoords = {}, endCoords = {};
$(document.body).bind("touchstart", function(event) {
    startCoords = endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchend", function(event) {
    $('p').text("Your touch on the axis: " + Math.abs(startCoords.pageX-endCoords.pageX) + "x, " + Math.abs(startCoords.pageY-endCoords.pageY) + "y");
});

Note:
None of the above examples are tested, hopes it works!
Math.abs gives me the absolute value of a number eg: -5 becomes 5

残疾 2024-12-07 01:10:51

有一段简化的代码,我用来检测 .myelement 的滑动手势,原来它是滑块画廊

$(function() {
    var diff, tchs, del = 150,
    clk = function(el){
        if ( typeof(tchs) !== 'object' ) return; //we have nothing to do
        if ( (diff - tchs[tchs.length - 1].pageX) < 0 ) { //swipe right

        }
        else if ( (diff - tchs[tchs.length - 1].pageX) > 0 ) { //swipe left

        }
    };  
    $('.myelement').bind('touchstart touchmove', function(ev){
            var oev = ev.originalEvent, el = $(this);
            switch( ev.type.charAt(5) ){
                case 's': //touch start
                    diff = oev.pageX;
                    window.setTimeout(clk, del, el);
                break;
                case 'm': //touch move
                    tchs = oev.touches;
                break;
            }
    });
});

UPD:顺便说一句,当我使用 MobiOne 版本 2.0.0M2 测试中心软件时,它已将 touchend pageX 值设置为我的值预期的,所以这听起来很糟糕,如果您无法快速访问真实设备,可能很容易混淆。

UPD2:好的,受到积极反馈的启发:)实现了有点复杂的版本,它允许检测右、左、上、下滑动,它还需要清理,但你明白了。

$(function () {
    var ftch, // first touch cache
    lck = Math.sin(Math.PI / 4); //lock value, sine of 45 deg configurable

    var defSwipeDir = function (el, tchs) { // need define swaping direction, for better UX
        if (typeof (tchs) !== 'object') return 0; // check if there was any movements since   first touch, if no return 0
        var ltch = tchs[tchs.length - 1], // last touch object
            dx = ltch.pageX - ftch.pageX,
            dy = ltch.pageY - ftch.pageY,
            hyp = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)),
            sin = dy / hyp,
            cos = dx / hyp,
            dir;

        if (Math.abs(cos) >= lck) { // left or right swape
            dir = cos > 0 ? 'r' : 'l';
        } else { // up or down
            dir = sin < 0 ? 'u' : 'd';
        }
        el.trigger('swipe', dir); // trigger custom swipe event
        return dir; // and return direction too
    }

    $('.myelementTouchDetection').on('touchstart touchmove swipe', function (ev, d) {
        var oev = ev.originalEvent,
            myelementTouchDetection = $(this),
            dir; // you may know swipes on move event too

        switch (ev.type) {
            case 'touchstart':
                ftch = oev;
                break;
            case 'touchmove':
                dir = defSwipeDir(myelementTouchDetection, oev.touches);
                return false // cancel default behaiviour
                break;
            case 'swipe':
                switch (d) {
                    case 'r': // swipe right
                        console.log('swipe right');
                        break;
                    case 'l': // swipe left
                        console.log('swipe left');
                        break;
                    case 'u': // swipe up
                        console.log('swipe up');
                        break;
                    case 'd': // swipe down
                        console.log('swipe down');
                        break;
                }
                break;
        }
    })
});

There is simplified piece of code I am used to detect swiping gestures for .myelement, in original it was slider gallery

$(function() {
    var diff, tchs, del = 150,
    clk = function(el){
        if ( typeof(tchs) !== 'object' ) return; //we have nothing to do
        if ( (diff - tchs[tchs.length - 1].pageX) < 0 ) { //swipe right

        }
        else if ( (diff - tchs[tchs.length - 1].pageX) > 0 ) { //swipe left

        }
    };  
    $('.myelement').bind('touchstart touchmove', function(ev){
            var oev = ev.originalEvent, el = $(this);
            switch( ev.type.charAt(5) ){
                case 's': //touch start
                    diff = oev.pageX;
                    window.setTimeout(clk, del, el);
                break;
                case 'm': //touch move
                    tchs = oev.touches;
                break;
            }
    });
});

UPD: by the way, when I used MobiOne version 2.0.0M2 Testing Center software it had put the touchend pageX value as I was expected, so it sounds bad implementation which may easy to confuse if you do not have quick access to real device.

UPD2: okay, inspired by positive feedback :) realized bit complicated version, which allows detect right, left, up and down swipes, it yet needs to be cleaned up, but you got the idea.

$(function () {
    var ftch, // first touch cache
    lck = Math.sin(Math.PI / 4); //lock value, sine of 45 deg configurable

    var defSwipeDir = function (el, tchs) { // need define swaping direction, for better UX
        if (typeof (tchs) !== 'object') return 0; // check if there was any movements since   first touch, if no return 0
        var ltch = tchs[tchs.length - 1], // last touch object
            dx = ltch.pageX - ftch.pageX,
            dy = ltch.pageY - ftch.pageY,
            hyp = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)),
            sin = dy / hyp,
            cos = dx / hyp,
            dir;

        if (Math.abs(cos) >= lck) { // left or right swape
            dir = cos > 0 ? 'r' : 'l';
        } else { // up or down
            dir = sin < 0 ? 'u' : 'd';
        }
        el.trigger('swipe', dir); // trigger custom swipe event
        return dir; // and return direction too
    }

    $('.myelementTouchDetection').on('touchstart touchmove swipe', function (ev, d) {
        var oev = ev.originalEvent,
            myelementTouchDetection = $(this),
            dir; // you may know swipes on move event too

        switch (ev.type) {
            case 'touchstart':
                ftch = oev;
                break;
            case 'touchmove':
                dir = defSwipeDir(myelementTouchDetection, oev.touches);
                return false // cancel default behaiviour
                break;
            case 'swipe':
                switch (d) {
                    case 'r': // swipe right
                        console.log('swipe right');
                        break;
                    case 'l': // swipe left
                        console.log('swipe left');
                        break;
                    case 'u': // swipe up
                        console.log('swipe up');
                        break;
                    case 'd': // swipe down
                        console.log('swipe down');
                        break;
                }
                break;
        }
    })
});
甜尕妞 2024-12-07 01:10:51

上面的 NULL 答案对我来说非常有用,只是你不能在 touchstart 绑定函数中将 startCoords 分配给 endCoords 。然后它们指向同一个对象,这样当 endCoords 更新时,startCoords 也会更新。当 touchend 事件触发时,startCoords 将始终等于 endCoords。

下面更新了代码。这对我在 iPad 3 上使用 iOS 6.0 上的 Safari 有效。还进行了编辑以修复数学和显示错误并删除 touchend 绑定函数内的 Math.abs() 。还在 touchmove-bound 函数中添加了 event.preventDefault() 调用,以便这些也可以在 iOS 上的 Google Chrome 上运行。

var startCoords = {}, endCoords = {};

$(document.body).bind("touchstart", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
    startCoords.pageX = event.originalEvent.targetTouches[0].pageX;
    startCoords.pageY = event.originalEvent.targetTouches[0].pageY;
});

$(document.body).bind("touchmove", function(event) {
    event.preventDefault();
    endCoords = event.originalEvent.targetTouches[0];
});

$(document.body).bind("touchend", function(event) {
    $('p').text("Your touch on the axis: " + (endCoords.pageX-startCoords.pageX) + "x, " + (endCoords.pageY-startCoords.pageY) + "y");
});

NULL's answer, above, worked great for me, except that you can't assign startCoords to endCoords in the touchstart-bound function. They then point to the same object so that when endCoords gets updated, so does startCoords. When the touchend event fires, startCoords will always equal endCoords.

Updated code below. This worked for me on an iPad 3 using Safari on iOS 6.0. Edited also to fix a math and display error and remove Math.abs() inside the touchend-bound function. Also added an event.preventDefault() call inside the touchmove-bound function, so that these would work on Google Chrome on iOS as well.

var startCoords = {}, endCoords = {};

$(document.body).bind("touchstart", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
    startCoords.pageX = event.originalEvent.targetTouches[0].pageX;
    startCoords.pageY = event.originalEvent.targetTouches[0].pageY;
});

$(document.body).bind("touchmove", function(event) {
    event.preventDefault();
    endCoords = event.originalEvent.targetTouches[0];
});

$(document.body).bind("touchend", function(event) {
    $('p').text("Your touch on the axis: " + (endCoords.pageX-startCoords.pageX) + "x, " + (endCoords.pageY-startCoords.pageY) + "y");
});
可爱咩 2024-12-07 01:10:51

这对我有用......

$('.someClass').bind('touchmove',function(e){
  e.preventDefault();
  var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  var elm = $(this).offset();
  var x = touch.pageX - elm.left;
  var y = touch.pageY - elm.top;
  if(x < $(this).width() && x > 0){
      if(y < $(this).height() && y > 0){
              //your code here
      }
     }
});

Here is what works for me....

$('.someClass').bind('touchmove',function(e){
  e.preventDefault();
  var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  var elm = $(this).offset();
  var x = touch.pageX - elm.left;
  var y = touch.pageY - elm.top;
  if(x < $(this).width() && x > 0){
      if(y < $(this).height() && y > 0){
              //your code here
      }
     }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文