2011-08-17 30 views
17

我在iPhone上玩touchstart和touchend事件。我構建了一個帶有div的示例頁面,如果您觸摸它並滾動頁面,它應該返回開始和結束位置的y座標。jQuery(Swipe vs. Touch)pageX和pageY繼續返回0

鏈接: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上該網頁,然而,警報不斷報告這兩個值爲零。有人看到我有什麼不對嗎?

UPDATE:

我碰到這段代碼在jQuery Mobile的項目絆倒:https://github.com/jquery/jquery-mobile/issues/734

註釋它從它伸出:

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

這並不是說爲什麼就是這樣,但至少我發現有人看到同樣的事情。將挖掘該頁面上的示例代碼,以查看解決方案是否存在。

UPDATE II:

好了,通過上面的鏈接示例代碼看後,看起來這將返回的實際值:

e.originalEvent.touches[0].pageY 

美中不足的是,我現在意識到,這不是我需要。它會返回我將該事件附加到與HTML文檔相關的對象內的對象內的區域的Y偏移量,而不是瀏覽器窗口。

我的目標是找出屏幕上觸摸開始的位置以及結束位置......然後比較這些值。如果它們有點不同,那麼我們就會執行滑動操作......而不是觸摸。

UPDATE III:

我也發現引用這些例子:

e.originalEvent.touches[0].pageX 

event.targetTouches[0].pageY 

雖然我似乎無法得到那些要麼工作。兩者都返回未定義的錯誤。

UPDATE IV:

它看起來像一個解決方案是在文檔本身到軌道偏移()。我可以將一個touchend事件應用到文檔中,然後檢查它是否偏移。

問題在於,我的touchend事件將首先觸發我的頁面上的元素,然後它會在文檔上觸發它(冒泡)。所以我不能真正確定它是否是觸摸或滑動之前我需要找出對象touchend事件做什麼。

還在琢磨這一個...

+0

怪異,不knwo關於手機,但工作正常點擊http://jsfiddle.net/nH2PU/ – Sinetheta

+1

我希望這是不會有這麼多的一個難倒的的。 ;) –

+0

Android中出現同樣的情況(2.2.2) – NoBugs

回答

19

好快的答案是當手指離開屏幕(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

+0

我發現在最後一個例子中,您在Y軸上寫了兩次絕對值「$('p')。text(」Your touch on軸......「 – Arabam

+0

@Arabam現在已經修復了,想想兩年後會發現類型錯誤:) – andlrc

+0

謝謝你提到'event.originalEvent' - 在Android上原來的事件是壓制targetTouches屬性並且破壞了一切!有趣的是,這不是iOS上的問題 - 使其更難調試。 – jocull

1

這裏是什麼對我工程....

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

有被簡化的代碼,我用來檢測刷卡對於.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屬性值檢測中心軟件,因爲我是意料之中的,這樣聽起來BA d實現,如果您沒有快速訪問真實設備,可能容易混淆。

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

上面的NULL的答案對我很好,除了你不能在touchstart-bound函數中指定startCoords到endCoords。然後他們指向相同的對象,以便在endCoords得到更新時,startCoords也會更新。當觸發事件觸發時,startCoords將始終等於endCoords。

更新後的代碼如下。這適用於在iOS 6.0上使用Safari的iPad 3。編輯也修復數學和顯示錯誤,並刪除數學。abs()在touchend-bound函數內。還在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"); 
});