it-swarm.com.de

verhindern Sie den Touchstart beim Wischen

Ich habe eine scrollbare Liste auf einem mobilen Gerät. Sie möchten, dass die Benutzer die Liste durch Wischen durchblättern können und durch Tippen eine Zeile auswählen. 

Der Haken verbindet die beiden. Ich möchte nicht, dass eine Zeile ausgewählt wird, wenn Sie tatsächlich durch die Liste scrollen. Folgendes habe ich gefunden:

Wird beim Scrollen nicht ausgelöst: 

  • klicken
  • mouseup 

Triggert beim Scrollen:

  • maus nach unten 
  • touchstart 
  • touchend 

Die einfache Lösung besteht darin, beim Klick-Ereignis zu bleiben. Was wir jedoch feststellen, ist, dass es bei bestimmten Blackberry-Geräten zu einer sehr merklichen Verzögerung zwischen dem Touchstart und dem Auslösen von Klick oder Mouseup kommt. Diese Verzögerung ist erheblich genug, um sie auf diesen Geräten unbrauchbar zu machen.

So bleiben uns die anderen Möglichkeiten. Mit diesen Optionen können Sie jedoch durch die Liste blättern, ohne die Zeile auszulösen, die Sie berührt haben, um den Bildlauf zu starten.

Was ist die beste Vorgehensweise, um dieses Problem zu lösen? 

35
DA.
var touchmoved;
$('button').on('touchend', function(e){
    if(touchmoved != true){
        // button click action
    }
}).on('touchmove', function(e){
    touchmoved = true;
}).on('touchstart', function(){
    touchmoved = false;
});
40

Grundsätzlich möchten Sie herausfinden, was ein Wischvorgang ist und was ein Klick ist.

Wir können einige Bedingungen festlegen:

  1. Wischen ist, wenn Sie den Punkt p1 berühren, dann den Finger zum Punkt p2 bewegen, während der Finger immer noch auf dem Bildschirm angezeigt wird, und dann loslassen.
  2. Ein Klick ertönt, wenn Sie auf das erste Element tippen und auf dasselbe Element tippen.

Wenn Sie also die Koordinaten Ihrer touchStart speichern, können Sie die Differenz bei touchEnd messen. Wenn die Änderung groß genug ist, betrachten Sie sie als Wischbewegung, andernfalls als Klick.

Wenn Sie es wirklich ordentlich machen wollen, können Sie auch feststellen, über welches Element Sie während einer touchMove mit dem Finger "schweben". Wenn Sie sich noch nicht bei dem Element befinden, auf das Sie den Klick gestartet haben, können Sie es ausführen eine clickCancel-Methode, die Markierungen entfernt usw.

// grab an element which you can click just as an example
var clickable = document.getElementById("clickableItem"),
// set up some variables that we need for later
currentElement,
clickedElement;

// set up touchStart event handler
var onTouchStart = function(e) {
    // store which element we're currently clicking on
    clickedElement = this;
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMove);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEnd);
};
// when the user swipes, update element positions to swipe
var onTouchMove = function(e) {
    // ... do your scrolling here

    // store current element
    currentElement = document.elementFromPoint(x, y);
    // if the current element is no longer the same as we clicked from the beginning, remove highlight
    if(clickedElement !== currentElement) {
        removeHighlight(clickedElement);
    }
};
// this is what is executed when the user stops the movement
var onTouchEnd = function(e) {
    if(clickedElement === currentElement) {
        removeHighlight(clickedElement);
        // .... execute click action
    }

    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMove);
    this.removeEventListener("touchEnd", onTouchEnd);
};
function addHighlight(element) {
    element.className = "highlighted";
}
function removeHighlight(element) {
    element.className = "";
}
clickable.addEventListener("touchStart", onTouchStart);

Dann müssen Sie auch Listener zu einem scrollbaren Element hinzufügen. Dort müssen Sie sich jedoch keine Gedanken darüber machen, was passiert, wenn sich der Finger zwischen touchStart und touchEnd bewegt.

var scrollable = document.getElementById("scrollableItem");

// set up touchStart event handler
var onTouchStartScrollable = function(e) {
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMoveScrollable);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEndScrollable);
};
// when the user swipes, update element positions to swipe
var onTouchMoveScrollable = function(e) {
    // ... do your scrolling here
};
// this is what is executed when the user stops the movement
var onTouchEndScrollable = function(e) {
    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMoveScrollable);
    this.removeEventListener("touchEnd", onTouchEndScrollable);
};
scrollable.addEventListener("touchStart", onTouchStartScrollable);

// Simon A.

Hier ist das, worauf ich schließlich gekommen bin, um zu ermöglichen, dass eine Liste von Elementen per Swipe scrollbar ist, aber auch jedes Element über ein Antippen "auslösbar" ist. Darüber hinaus können Sie weiterhin eine Tastatur verwenden (mit Onclick). 

Ich denke, das ist der Antwort von Netlight_Digital_Media ähnlich. Ich muss das ein bisschen mehr studieren. 

$(document)
// log the position of the touchstart interaction
.bind('touchstart', function(e){ 
  touchStartPos = $(window).scrollTop();
})
// log the position of the touchend interaction
.bind('touchend', function(e){
  // calculate how far the page has moved between
  // touchstart and end. 
  var distance = touchStartPos - $(window).scrollTop();

  var $clickableItem; // the item I want to be clickable if it's NOT a swipe

  // adding this class for devices that
  // will trigger a click event after
  // the touchend event finishes. This 
  // tells the click event that we've 
  // already done things so don't repeat

  $clickableItem.addClass("touched");      

  if (distance > 20 || distance < -20){
        // the distance was more than 20px
        // so we're assuming they intended
        // to swipe to scroll the list and
        // not selecting a row. 
    } else {
        // we'll assume it was a tap 
        whateverFunctionYouWantToTriggerOnTapOrClick()
    }
});


$($clickableItem).live('click',function(e){
 // for any non-touch device, we need 
 // to still apply a click event
 // but we'll first check to see
 // if there was a previous touch
 // event by checking for the class
 // that was left by the touch event.
if ($(this).hasClass("touched")){
  // this item's event was already triggered via touch
  // so we won't call the function and reset this for
  // the next touch by removing the class
  $(this).removeClass("touched");
} else {
  // there wasn't a touch event. We're
  // instead using a mouse or keyboard
  whateverFunctionYouWantToTriggerOnTapOrClick()
}
});
17
DA.

Zitat von DA .:

Dies ist ein Arbeitsbeispiel:

var touch_pos;
$(document).on('touchstart', '.action-feature', function(e) {
  e.preventDefault();
  touch_pos = $(window).scrollTop();
}).on('click touchend', '.action-feature', function(e) {
  e.preventDefault();
  if(e.type=='touchend' && (Math.abs(touch_pos-$(window).scrollTop())>3)) return;
  alert("only accessed when it's a click or not a swipe");
});
6
josualeonard

Einige dieser Lösungen funktionierten für mich, aber am Ende stellte ich fest, dass diese leichtgewichtige Bibliothek einfacher einzurichten war.

Tocca.js: https://github.com/GianlucaGuarini/Tocca.js

Es ist ziemlich flexibel und erkennt sowohl Berührung als auch Streichen, Doppeltippen usw.

3
Patrice Wrex

Ich hatte das gleiche Problem, hier ist eine schnelle Lösung, die für mich funktioniert

$(document).on('touchstart', 'button', function(evt){ 
    var oldScrollTop = $(window).scrollTop();
    window.setTimeout( function() {
        var newScrollTop = $(window).scrollTop();
        if (Math.abs(oldScrollTop-newScrollTop)<3) $button.addClass('touchactive');
    }, 200);
});

anstatt Touchstart sofort zu behandeln, warten Sie einige Millisekunden (in diesem Beispiel 200ms), überprüfen Sie dann die Bildlaufposition, haben Sie die Bildlaufposition geändert.

2
Mahes

Ich bin auf diese elegante Lösung gestoßen, die mit jQuery wie ein Zauber wirkt. Mein Problem bestand darin, zu verhindern, dass Listenelemente während des Bildlaufs ihr Touch-Start-Ereignis aufrufen. Dies sollte auch zum Wischen funktionieren.

  1. binden Sie den Touchstart an jedes Element, das mit der Klasse "listObject" gescrollt oder gewischt wird.

    $('.listObject').live('touchstart', touchScroll);
    
  2. Weisen Sie dann jedem Element ein Datenobjekt attr zu, das die aufzurufende Funktion definiert

    <button class='listObject' data-object=alert('You are alerted !')>Alert Me</button>
    

Die folgende Funktion unterscheidet effektiv zwischen Tippen und Scrollen oder Wischen.

function touchScroll(e){

    var objTarget = $(event.target);

    if(objTarget.attr('data-object')){
        var fn = objTarget.attr('data-object'); //function to call if tapped    
    }   

    if(!touchEnabled){// default if not touch device
        eval(fn);
        console.log("clicked", 1);
        return;
    }

    $(e.target).on('touchend', function(e){
        eval(fn); //trigger the function
        console.log("touchEnd")      
        $(e.target).off('touchend');
    });

    $(e.target).on('touchmove', function(e){
        $(e.target).off('touchend');
        console.log("moved")
    }); 

}
1
alQemist

wenn Sie dies für mehrere Elemente tun möchten und Maus- und Zeigerereignisse benötigen:

var elems = $('YOURMULTISELECTOR'); // selector for multiple elements
elems.unbind('mousdown pointerdown touchstart touchmove mouseup pointerup touchend');
var elem = null;
elems.on('mousdown pointerdown touchstart', function (e) {
    elem = yourSingleSelector(e);
}).on('touchmove', function (e) {
    elem = null;                
}).on('mouseup pointerup touchend', function (e) { 
    if (elem == yourSingleSelector(e)) {                    
        // do something
    }
});
0
A.J.Bauer

jQuery Mobile hat ein Ereignis .tap() , das das erwartete Verhalten aufweist:

Das jQuery Mobile-Tap-Ereignis wird nach einem schnellen, vollständigen Berührungsereignis ausgelöst, das bei einem einzelnen Zielobjekt auftritt. Dies ist die Geste, die einem Standardklickereignis entspricht, das beim Freigabezustand der Berührungsgeste ausgelöst wird.

Dies muss die Frage nicht unbedingt beantworten, kann jedoch eine nützliche Alternative zu einigen sein.

0
Wex

Ich benutze dieses Codebit, so dass Schaltflächen nur dann ausgelöst werden (am Touchend), wenn nicht gewischt wird:

var startY;
var yDistance;

function touchHandler(event) {
    touch = event.changedTouches[0];
    event.preventDefault();
}

$('.button').on("touchstart", touchHandler, true);
$('.button').on("touchmove", touchHandler, true);

$('.button').on("touchstart", function(){
    startY = touch.clientY;
});

$('.button').on('touchend', function(){

    yDistance = startY - touch.clientY;

    if(Math.abs(yDist) < 30){

        //button response here, only if user is not swiping
        console.log("button pressed")
    }
});
0
LocDog

Ich habe das mit etwas anderer Arbeit gemacht. Es ist definitiv nicht sehr elegant und sicherlich nicht für die meisten Situationen geeignet, aber es hat für mich funktioniert. 

Ich habe toggleSlide () von jQuery verwendet, um die Eingabedivs zu öffnen und zu schließen, wobei die Folie beim Touchstart ausgelöst wurde. Das Problem war, dass sich der berührte div öffnen würde, wenn der Benutzer scrollen wollte. Um dies zu verhindern (oder um es umzukehren, bevor der Benutzer es merkte), fügte ich dem Dokument ein berührungsloses Ereignis hinzu, das das zuletzt berührte div schließen würde. 

Hier ist ein Code-Snippet:

var lastTouched;

document.addEventListener('touchmove',function(){
    lastTouched.hide();
});

$('#button').addEventListener('touchstart',function(){
    $('#slide').slideToggle();
    lastTouched = $('#slide');
});

Die globale Variable speichert das letzte berührte div. Wenn der Benutzer den Befehl wischt, blendet das document.touchmove -Ereignis dieses div aus. Manchmal flackert ein Div raus, aber es funktioniert so, wie ich es brauche, und es ist so einfach, dass ich es mir vorstellen kann.

0
Abraham Brookes