jQuery (Swipe vs. Touch) pageX и pageY продолжают возвращаться 0 - PullRequest
18 голосов
/ 18 августа 2011

Я играю с событиями touchstart и touchend на моем 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, предупреждение продолжает сообщать об обоих значениях как об нулевых. Кто-нибудь видит что-то не так с тем, что у меня есть?

UPDATE:

Я наткнулся на этот фрагмент кода в проекте 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 сначала сработает на элементе на моей странице, а затем сработает с документом (всплывающее окно). Поэтому я не могу определить, касалось ли это касания или касания, ДО того, как мне нужно выяснить, что делать с событием касания объектов.

Все еще размышляю над этим ...

Ответы [ 4 ]

20 голосов
/ 24 августа 2011

Хорошо, быстрый ответ: вы не можете обнаружить касание, когда палец покидает экран (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);
});

Теперь попробуйте коснуться вашего устройства!

Вот некоторые заключительные замечания: Сделайте переменные: 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");
});

Примечание:
Ни один из приведенных выше примеров не тестировался, надеюсь, он работает!
Math.abs дает мне абсолютное значениечисло например: -5 становится 5

2 голосов
/ 25 января 2013

Ответ NULL, выше, отлично работал для меня, за исключением того, что вы не можете назначить startCoords для endCoords в функции, связанной с началом прикосновения.Затем они указывают на один и тот же объект, так что когда endCoords обновляется, то же самое происходит и с startCoords.Когда событие touchend срабатывает, startCoords всегда будет равняться endCoords.

Обновленный код ниже.Это сработало для меня на iPad 3 с использованием Safari на iOS 6.0.Отредактировано также для исправления математических ошибок и ошибок отображения и удаления Math.abs () внутри функции, связанной с касаниями.Также добавлен вызов event.preventDefault () внутри функции привязки к движению, чтобы они работали и в Google Chrome на iOS.

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");
});
2 голосов
/ 18 мая 2012

Существует упрощенный фрагмент кода, который я использовал для обнаружения жестов смахивания для .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 TestingВ центре программного обеспечения было задано значение 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;
        }
    })
});
1 голос
/ 10 марта 2012

Вот что у меня работает ....

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