jQuery(Swipe vs. Touch)pageX和pageY一直返回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 ) 

它没有说明为什么会这样,但至少我发现其他人看到了同样的事情。 将挖掘该页面上的示例代码以查看解决方案是否存在。

更新II:

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

 e.originalEvent.touches[0].pageY 

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

我的目标是找出屏幕触摸开始的位置,结束的位置……然后比较值。 如果它们有点不同,那么我们就会进行滑动…而不是触摸。

更新III:

我也找到了这些例子的参考:

 e.originalEvent.touches[0].pageX event.targetTouches[0].pageY 

虽然我似乎无法让那些工作。 两者都返回未定义的错误。

更新IV:

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

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

还在思考这一个……

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

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

现在到了解决方法。 或称之为你想要的。 也许在touchend事件中没有检测是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); }); 

现在尝试点按您的设备!

最后的一些注释将是:make to variables: 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

有一段简化的代码用于检测.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; } }) }); 

上面的NULL的答案对我很有用,除了你不能在touchstart-bound函数中将startCoords分配给endCoords。 然后,它们指向同一个对象,以便在endCoords更新时,startCoords也会更新。 当touchend事件触发时,startCoords将始终等于endCoords。

更新了以下代码。 这适用于在iOS 3上使用Safari的iPad 3。 编辑也修复数学和显示错误,并删除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"); }); 

这对我有用….

 $('.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 } } });