18

iPhoneでタッチスタートイベントとタッチエンドイベントで遊んでいます。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

キャッチは、私は今、それが私が完全に必要としているわけではないことに気づきました。これは、ブラウザウィンドウではなく、イベントをHTMLドキュメントに関連して添付したオブジェクト内でタッチした領域のYオフセットを返します。

私の目標は、タッチが画面のどこから始まり、どこで終わったかを把握し、値を比較することです。それらがかなり異なる場合は、タッチではなく、スワイプが実行されたと見なします。

更新III:

私はこれらの例への参照も見つけています:

e.originalEvent.touches[0].pageX

event.targetTouches[0].pageY

私もそれらを機能させることができないようですが。どちらも未定義のエラーを返します。

更新IV:

1つの解決策は、ドキュメント自体のoffset()を追跡することのようです。ドキュメントにタッチエンドイベントを適用して、オフセットを確認できます。

これに伴う問題は、タッチエンドイベントが最初にページ上の要素でトリガーされ、次にドキュメントで発生することです(バブリング)。そのため、オブジェクトのタッチエンドイベントで何をするかを理解する必要がある前に、それがタッチであるかスワイプであるかを実際に判断することはできません。

まだこれを熟考しています...

4

4 に答える 4

20

簡単な答えは、指が画面から離れたときにタッチを検出できないということです ( 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定義する準備ができていれば、そこにいます: http://jsfiddle.net/Y4fHD/2/endCoords

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

今すぐあなたのデバイスをタップしてみてください!

いくつかの最終的な注意事項は次のstartCoordsとおりですendCoordstouchend

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 になります

于 2011-08-24T19:39:13.270 に答える
2

上記の NULL の答えは、touchstart バインド関数で startCoords を endCoords に割り当てることができないことを除いて、私にとってはうまくいきました。その後、それらは同じオブジェクトを指すため、endCoords が更新されると startCoords も更新されます。touchend イベントが発生すると、startCoords は常に endCoords と等しくなります。

以下のコードを更新しました。これは、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");
});
于 2013-01-24T23:22:50.580 に答える
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 値が設定されていたので、実際のデバイスにすばやくアクセスできない場合は混乱しやすい実装に聞こえます。

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;
        }
    })
});
于 2012-05-18T15:02:34.713 に答える
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
      }
     }
});
于 2012-03-10T14:47:32.213 に答える