Detectar un dedo deslizar a través de JavaScript en el iPhone y Android

¿Cómo se puede detectar que un usuario pasó su dedo en alguna dirección sobre una página web con JavaScript?

Me preguntaba si había una solución que trabajaría para los Web site en el iPhone y un teléfono androide.

Ejemplo de código simple de la vainilla JS:

document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchmove', handleTouchMove, false); var xDown = null; var yDown = null; function handleTouchStart(evt) { xDown = evt.touches[0].clientX; yDown = evt.touches[0].clientY; }; function handleTouchMove(evt) { if ( ! xDown || ! yDown ) { return; } var xUp = evt.touches[0].clientX; var yUp = evt.touches[0].clientY; var xDiff = xDown - xUp; var yDiff = yDown - yUp; if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/ if ( xDiff > 0 ) { /* left swipe */ } else { /* right swipe */ } } else { if ( yDiff > 0 ) { /* up swipe */ } else { /* down swipe */ } } /* reset values */ xDown = null; yDown = null; }; 

Probado en Android.

Utilice evt.originalEvent.touches lugar de evt.touches si está trabajando con JQuery.

He encontrado este plugin jquery touchwipe que funciona tanto en mi primera generación de ipod touch y mi droide increíble. http://www.netcu.de/jquery-touchwipe-iphone-ipad-library

¿Has probado hammer.js? http://eightmedia.github.com/hammer.js/ También funciona en Windows Phones ..

Lo que he usado antes es que tienes que detectar el evento mousedown, grabar su ubicación x, y (lo que sea relevante) y luego detectar el evento mouseup, y restar los dos valores.

JQuery Mobile también incluye soporte de swipe: http://api.jquerymobile.com/swipe/

Ejemplo

 $("#divId").on("swipe", function(event) { alert("It's a swipe!"); }); 

Basado en la respuesta de @ givanse, esto es cómo usted podría hacerlo con classes :

 class Swipe { constructor(element) { this.xDown = null; this.yDown = null; this.element = typeof(element) === 'string' ? document.querySelector(element) : element; this.element.addEventListener('touchstart', function(evt) { this.xDown = evt.touches[0].clientX; this.yDown = evt.touches[0].clientY; }.bind(this), false); } onLeft(callback) { this.onLeft = callback; return this; } onRight(callback) { this.onRight = callback; return this; } onUp(callback) { this.onUp = callback; return this; } onDown(callback) { this.onDown = callback; return this; } handleTouchMove(evt) { if ( ! this.xDown || ! this.yDown ) { return; } var xUp = evt.touches[0].clientX; var yUp = evt.touches[0].clientY; this.xDiff = this.xDown - xUp; this.yDiff = this.yDown - yUp; if ( Math.abs( this.xDiff ) > Math.abs( this.yDiff ) ) { // Most significant. if ( this.xDiff > 0 ) { this.onLeft(); } else { this.onRight(); } } else { if ( this.yDiff > 0 ) { this.onUp(); } else { this.onDown(); } } // Reset values. this.xDown = null; this.yDown = null; } run() { this.element.addEventListener('touchmove', function(evt) { this.handleTouchMove(evt).bind(this); }.bind(this), false); } } 

Puedes usarlo de esta manera:

 // Use class to get element by string. var swiper = new Swipe('#my-element'); swiper.onLeft(function() { alert('You swiped left.') }); swiper.run(); // Get the element yourself. var swiper = new Swipe(document.getElementById('#my-element')); swiper.onLeft(function() { alert('You swiped left.') }); swiper.run(); // One-liner. (new Swipe('#my-element')).onLeft(function() { alert('You swiped left.') }).run(); 

He encontrado @givanse brillante respuesta para ser el más fiable y compatible a través de múltiples navegadores móviles para el registro de acciones de deslizamiento.

Sin embargo, hay un cambio en su código necesario para que funcione en los navegadores móviles de hoy en día que utilizan jQuery .

event.touches no existirá si jQuery se utiliza y resulta en undefined y debe ser reemplazado por event.originalEvent.touches . Sin jQuery , event.touches debería funcionar bien.

Así que la solución se convierte,

 document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchmove', handleTouchMove, false); var xDown = null; var yDown = null; function handleTouchStart(evt) { xDown = evt.originalEvent.touches[0].clientX; yDown = evt.originalEvent.touches[0].clientY; }; function handleTouchMove(evt) { if ( ! xDown || ! yDown ) { return; } var xUp = evt.originalEvent.touches[0].clientX; var yUp = evt.originalEvent.touches[0].clientY; var xDiff = xDown - xUp; var yDiff = yDown - yUp; if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/ if ( xDiff > 0 ) { /* left swipe */ } else { /* right swipe */ } } else { if ( yDiff > 0 ) { /* up swipe */ } else { /* down swipe */ } } /* reset values */ xDown = null; yDown = null; }; 

Probado en:

  • Android : Chrome, navegador de UC
  • IOS : Safari, Chrome, Navegador de UC

He reempaquetado TouchWipe como un complemento jquery corto: detectSwipe

Algunos mod de uppest respuesta (no puedo comentar …) para hacer frente a golpes cortos

 document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchmove', handleTouchMove, false); var xDown = null; var yDown = null; function handleTouchStart(evt) { xDown = evt.touches[0].clientX; yDown = evt.touches[0].clientY; }; function handleTouchMove(evt) { if ( ! xDown || ! yDown ) { return; } var xUp = evt.touches[0].clientX; var yUp = evt.touches[0].clientY; var xDiff = xDown - xUp; var yDiff = yDown - yUp; if(Math.abs( xDiff )+Math.abs( yDiff )>150){ //to deal with to short swipes if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/ if ( xDiff > 0 ) {/* left swipe */ alert('left!'); } else {/* right swipe */ alert('right!'); } } else { if ( yDiff > 0 ) {/* up swipe */ alert('Up!'); } else { /* down swipe */ alert('Down!'); } } /* reset values */ xDown = null; yDown = null; } }; 

Trashold, swap de tiempo de espera, swipeBlockElems add.

 document.addEventListener('touchstart', handleTouchStart, false); document.addEventListener('touchmove', handleTouchMove, false); document.addEventListener('touchend', handleTouchEnd, false); const SWIPE_BLOCK_ELEMS = [ 'swipBlock', 'handle', 'drag-ruble' ] let xDown = null; let yDown = null; let xDiff = null; let yDiff = null; let timeDown = null; const TIME_TRASHOLD = 200; const DIFF_TRASHOLD = 130; function handleTouchEnd() { let timeDiff = Date.now() - timeDown; if (Math.abs(xDiff) > Math.abs(yDiff)) { /*most significant*/ if (Math.abs(xDiff) > DIFF_TRASHOLD && timeDiff < TIME_TRASHOLD) { if (xDiff > 0) { // console.log(xDiff, TIME_TRASHOLD, DIFF_TRASHOLD) SWIPE_LEFT(LEFT) /* left swipe */ } else { // console.log(xDiff) SWIPE_RIGHT(RIGHT) /* right swipe */ } } else { console.log('swipeX trashhold') } } else { if (Math.abs(yDiff) > DIFF_TRASHOLD && timeDiff < TIME_TRASHOLD) { if (yDiff > 0) { /* up swipe */ } else { /* down swipe */ } } else { console.log('swipeY trashhold') } } /* reset values */ xDown = null; yDown = null; timeDown = null; } function containsClassName (evntarget , classArr) { for (var i = classArr.length - 1; i >= 0; i--) { if( evntarget.classList.contains(classArr[i]) ) { return true; } } } function handleTouchStart(evt) { let touchStartTarget = evt.target; if( containsClassName(touchStartTarget, SWIPE_BLOCK_ELEMS) ) { return; } timeDown = Date.now() xDown = evt.touches[0].clientX; yDown = evt.touches[0].clientY; xDiff = 0; yDiff = 0; } function handleTouchMove(evt) { if (!xDown || !yDown) { return; } var xUp = evt.touches[0].clientX; var yUp = evt.touches[0].clientY; xDiff = xDown - xUp; yDiff = yDown - yUp; } 

Si alguien está intentando utilizar jQuery Mobile en Android y tiene problemas con la detección de deslizamiento JQM

(Tuve algunos en Xperia Z1, Galaxy S3, Nexus 4 y algunos teléfonos Wiko también) esto puede ser útil:

  //Fix swipe gesture on android if(android){ //Your own device detection here $.event.special.swipe.verticalDistanceThreshold = 500 $.event.special.swipe.horizontalDistanceThreshold = 10 } 

No se detectó Android en Android, a menos que fuera un golpe muy largo, preciso y rápido.

Con estas dos líneas funciona correctamente

Dos usados:

JQuery móvil: el trabajo en la mayoría de los casos y especialmente cuando se está desarrollando applicaion que utiliza otro plugin jQuery entonces mejor utilizar jQuery controles móviles para esto. Visite aquí: https://www.w3schools.com/jquerymobile/jquerymobile_events_touch.asp

Hora del martillo ! Una de las mejores, ligeras y rápidas bibliotecas basadas en javascript. Visite aquí: https://hammerjs.github.io/

Tuve problemas con el manipulador touchend disparando continuamente mientras el usuario estaba arrastrando un dedo alrededor. No sé si eso es debido a algo que estoy haciendo mal o no, pero lo rewired esto para acumular movimientos con touchmove y touchend realmente dispara la devolución de llamada.

También necesité tener un número grande de estos casos y así que agregué habilitar / deshabilitar métodos.

Y un umbral en el que no se dispara un golpe corto. Toque el cero con los contadores cada vez.

Usted puede cambiar el target_node sobre la marcha. Habilitar en la creación es opcional.

 /** Usage: */ touchevent = new Modules.TouchEventClass(callback, target_node); touchevent.enable(); touchevent.disable(); /** * * Touch event module * * @param method set_target_mode * @param method __touchstart * @param method __touchmove * @param method __touchend * @param method enable * @param method disable * @param function callback * @param node target_node */ Modules.TouchEventClass = class { constructor(callback, target_node, enable=false) { /** callback function */ this.callback = callback; this.xdown = null; this.ydown = null; this.enabled = false; this.target_node = null; /** move point counts [left, right, up, down] */ this.counts = []; this.set_target_node(target_node); /** Enable on creation */ if (enable === true) { this.enable(); } } /** * Set or reset target node * * @param string/node target_node * @param string enable (optional) */ set_target_node(target_node, enable=false) { /** check if we're resetting target_node */ if (this.target_node !== null) { /** remove old listener */ this.disable(); } /** Support string id of node */ if (target_node.nodeName === undefined) { target_node = document.getElementById(target_node); } this.target_node = target_node; if (enable === true) { this.enable(); } } /** enable listener */ enable() { this.enabled = true; this.target_node.addEventListener("touchstart", this.__touchstart.bind(this)); this.target_node.addEventListener("touchmove", this.__touchmove.bind(this)); this.target_node.addEventListener("touchend", this.__touchend.bind(this)); } /** disable listener */ disable() { this.enabled = false; this.target_node.removeEventListener("touchstart", this.__touchstart); this.target_node.removeEventListener("touchmove", this.__touchmove); this.target_node.removeEventListener("touchend", this.__touchend); } /** Touchstart */ __touchstart(event) { event.stopPropagation(); this.xdown = event.touches[0].clientX; this.ydown = event.touches[0].clientY; /** reset count of moves in each direction, [left, right, up, down] */ this.counts = [0, 0, 0, 0]; } /** Touchend */ __touchend(event) { let max_moves = Math.max(...this.counts); if (max_moves > 500) { // set this threshold appropriately /** swipe happened */ let index = this.counts.indexOf(max_moves); if (index == 0) { this.callback("left"); } else if (index == 1) { this.callback("right"); } else if (index == 2) { this.callback("up"); } else { this.callback("down"); } } } /** Touchmove */ __touchmove(event) { event.stopPropagation(); if (! this.xdown || ! this.ydown) { return; } let xup = event.touches[0].clientX; let yup = event.touches[0].clientY; let xdiff = this.xdown - xup; let ydiff = this.ydown - yup; /** Check x or y has greater distance */ if (Math.abs(xdiff) > Math.abs(ydiff)) { if (xdiff > 0) { this.counts[0] += Math.abs(xdiff); } else { this.counts[1] += Math.abs(xdiff); } } else { if (ydiff > 0) { this.counts[2] += Math.abs(ydiff); } else { this.counts[3] += Math.abs(ydiff); } } } } 
  • Descargar el archivo a la carpeta de descargas ios / android using phonegap
  • ¿Cordova evita la arrastrar webview en el campo de enfoque?
  • Abrir aplicación de Android desde una página web
  • ¿Cómo mostrar fórmulas matemáticas en mi aplicación Android?
  • Cómo utilizar navigator.app.exitApp ()?
  • Inyección de puente Javascript en WebView
  • El evento JavaScript touchend no se disparará en Android
  • Biblioteca Raphaeljs y SmartPhones
  • ToolBarAndroid no representa en ReactNative
  • Deshabilitar el almacenamiento en caché, las cookies y todo lo demás en un WebView
  • Cómo arreglar "Falta un arrastre mientras esperamos la respuesta de WebCore para tocar hacia abajo"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.