w3schools start ontouchmove ontouchend event changedtouches javascript jquery scroll touch touch-events

javascript - start - ontouchmove jquery



evitar touchstart al deslizar (12)

Tengo una lista desplegable en un dispositivo móvil. Quieren que las personas puedan desplazarse por la lista deslizando y también seleccionar una fila tocando.

La trampa es combinar los dos. No quiero que se seleccione una fila si realmente está desplazando la lista. Esto es lo que he encontrado:

No se dispara cuando se desplaza:

  • hacer clic
  • mouseup

Se dispara cuando se desplaza:

  • ratón hacia abajo
  • touchstart
  • touchend

La solución simple es quedarse con el evento click. Pero lo que estamos encontrando es que en ciertos dispositivos Blackberry, hay un retraso MUY notable entre touchstart y luego desencadenando un clic o un mouseup. Este retraso es lo suficientemente significativo como para que no se pueda usar en esos dispositivos.

Entonces eso nos deja con las otras opciones. Sin embargo, con esas opciones, puede desplazarse por la lista sin activar la fila que tocó para iniciar el desplazamiento.

¿Cuál es la mejor práctica aquí para resolver esto?


Algunas de estas soluciones funcionaron para mí, pero al final descubrí que esta biblioteca liviana era más sencilla de configurar.

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

Es bastante flexible y detecta el tacto y el deslizamiento, doble toque, etc.


Citando de DA .:

Este es un ejemplo de trabajo:

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


Esto es lo que finalmente se me ocurrió para permitir que una lista de artículos se pueda desplazar mediante deslizamiento, pero también que cada elemento sea "activable" mediante un toque. Además, puede usarlo con un teclado (usando onclick).

Creo que esto es similar a la respuesta de Netlight_Digital_Media. Necesito estudiar eso un poco más.

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


Hice esto con un trabajo diferente. Definitivamente no es muy elegante y ciertamente no es adecuado para la mayoría de las situaciones, pero funcionó para mí.

He estado usando jQuery''s toggleSlide () para abrir y cerrar entradas de divs, disparando la diapositiva en touchstart. El problema era que cuando el usuario quería desplazarse, el div tocado se abría. Para evitar que esto suceda, (o para revertirlo antes de que el usuario lo notara) agregué un evento touchslide al documento que cerraría el último div tocado.

Con más profundidad, aquí hay un fragmento de código:

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

La variable global almacena el último div tocado, y si el usuario se desliza, el evento document.touchmove oculta ese div. A veces obtienes un destello de una div, pero funciona para lo que necesito, y es lo suficientemente simple como para que yo se me ocurra.


Implementé una solución más fácil al hacer esto:

$el.mouseover(function() { if (jQuery.browser.mobile) { //your javscript function } });


Lo que básicamente quieres hacer es detectar qué es un deslizamiento y qué es un clic.

Podemos establecer algunas condiciones:

  1. Deslizar es cuando tocas en el punto p1 , luego mueves tu dedo hacia el punto p2 mientras sigues teniendo el dedo en la pantalla y luego lo sueltas.
  2. Un clic es cuando toca comenzar a tocar y finalizar tocando en el mismo elemento.

Por lo tanto, si almacena las coordenadas del lugar donde ocurrió su touchStart , puede medir la diferencia en touchEnd . Si el cambio es lo suficientemente grande, considéralo un deslizamiento, de lo contrario, considéralo un clic.

Además, si quieres hacerlo realmente ordenado, también puedes detectar qué elemento estás "moviendo" sobre tu dedo durante un touchMove , y si todavía no estás en el elemento en el que comenzaste el clic, puedes ejecutar un método clickCancel que elimina los reflejos, etc.

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

Luego, tendrá que agregar oyentes a su elemento desplazable también, pero allí no tendrá que preocuparse por lo que sucederá si el dedo se movió entre touchStart y touchEnd .

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.


Me encontré con esta elegante solución que funciona como un encanto usando jQuery. Mi problema fue evitar que los elementos de la lista llamaran a su evento de inicio táctil durante el desplazamiento. Esto también debería funcionar para deslizar.

  1. unir touchstart a cada elemento que se desplazará o deslizará usando una clase ''listObject''

    $(''.listObject'').live(''touchstart'', touchScroll);

  2. Luego, a cada elemento, asigne un objeto de datos attr que define la función que se va a llamar

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

La siguiente función diferenciará efectivamente entre un toque y desplazamiento o deslizamiento.

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


Tuve el mismo problema, aquí hay una solución rápida que funciona para mí

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

Básicamente, en lugar de manejar Touchstart inmediatamente, espere unos milisegundos (200 ms en este ejemplo), luego verifique la posición de desplazamiento, haya cambiado la posición de desplazamiento, y luego no necesitemos manejar el inicio táctil.


Uso este código para que los botones solo se activen (en touchend) si no están encendidos:

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


jQuery Mobile tiene un evento .tap() que parece tener el comportamiento esperado:

El evento de toque de jQuery Mobile se activa después de un evento táctil rápido y completo que ocurre en un único objeto de destino. Es el gesto equivalente de un evento de clic estándar que se desencadena en el estado de liberación del gesto táctil.

Esto podría no necesariamente responder a la pregunta, pero podría ser una alternativa útil para algunos.


si desea hacer esto para múltiples elementos y también necesita eventos de mouse y puntero:

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


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