jQuery (Swipe vs. Touch) pageX and pageY keep returning 0

前端 未结 4 921
忘掉有多难
忘掉有多难 2020-12-25 14:10

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 coordinate

相关标签:
4条回答
  • 2020-12-25 14:48

    Ok the quick answer is you can't detect a touch when the finger leaves the screen (touchend).

    My first example proves that: 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 has ended.

    Bind the handler on the touchmove event: 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

    $(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/

    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

    $(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/

    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

    0 讨论(0)
  • 2020-12-25 14:52

    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
          }
         }
    });
    
    0 讨论(0)
  • 2020-12-25 15:04

    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.

    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.

    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");
    });
    
    0 讨论(0)
  • 2020-12-25 15:05

    There is simplified piece of code I am used to detect swiping gestures for .myelement, in original it was slider gallery

    $(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.

    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.

    $(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;
            }
        })
    });
    
    0 讨论(0)
提交回复
热议问题