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
jQuery (Swipe vs. Touch) pageX and pageY keep returning 0
提问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
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 touchend
event because the the touch hasended.
现在到解决方法。或者称之为你想要的。也许touchend
因为触摸已经结束,所以不检测事件是有意义的。
Bind the handler on the touchmove
event: 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 endCoords
to 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 touchstart
defines the endCoords
variable 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 endCoords
to 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: startCoords
and endCoords
then use these in the touchend
event: http://jsfiddle.net/Y4fHD/3/
最后的一些注意事项是:做出变量:startCoords
和endCoords
然后在使用这些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.abs
gives 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
}
}
});