jQuery (Swipe vs. Touch) pageX 和 pageY 一直返回 0

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

jQuery (Swipe vs. Touch) pageX and pageY keep returning 0

jquerytouch-eventswipe-gesturepagey

提问by DA.

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.

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

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

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

the jQuery:

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?

但是,当我在 iPhone 上加载该页面时,警报一直将两个值报告为零。有人看到我的东西有什么问题吗?

UPDATE:

更新:

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

我在 jQuery Mobile 项目中偶然发现了这段代码: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 whythat'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.

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

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.

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

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.

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

Still pondering this one...

还在琢磨这个。。。

回答by andlrc

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

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

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

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

Now to the workaround. Or call it what you want. Maybe it makes sense not detection on the touchendevent because the the touch hasended.

现在到解决方法。或者称之为你想要的。也许touchend因为触摸已经结束,所以不检测事件是有意义的。

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

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

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

And then use the variable endCoordsto determinate the last touch

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

$(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 touchstartdefines the endCoordsvariable we are there: http://jsfiddle.net/Y4fHD/2/

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

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

And then use the variable endCoordsto determinate the last touch

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

$(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: startCoordsand endCoordsthen use these in the touchendevent: http://jsfiddle.net/Y4fHD/3/

最后的一些注意事项是:做出变量: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");
});

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

注意:
以上示例均未经过测试,希望它有效!
Math.abs给我一个数字的绝对值,例如:-5 变成 5

回答by dmi3y

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

有一段简化的代码,我用来检测 .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: 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.

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

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.

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;
        }
    })
});

回答by Joseph Cheek

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.

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

更新了下面的代码。这对我在 iOS 6.0 上使用 Safari 的 iPad 3 有效。还编辑以修复数学和显示错误并删除 touchend-bound 函数内的 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");
});

回答by TJS101

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
      }
     }
});