通过iPhone和Android上的JavaScript检测手指滑动

你怎么能检测到用户用JavaScript在网页上向某个方向滑动手指?

我想知道是否有一个解决scheme,可以在iPhone和Android手机上的网站工作。

简单的香草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; }; 

在Androidtesting。

如果您正在使用JQuery,请使用evt.originalEvent.touches而不要使用evt.originalEvent.touches

我发现这个jquery touchwipe插件适用于我的第一代iPod touch和我的机器人不可思议。 http://www.netcu.de/jquery-touchwipe-iphone-ipad-library

我之前使用过的是你必须检测mousedown事件,logging它的x,y位置(以相关为准),然后检测mouseup事件,并减去这两个值。

基于@ givanse的回答,这就是你如何用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); } } 

你可以像这样使用它:

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

jQuery Mobile还包含滑动支持: http : //api.jquerymobile.com/swipe/

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

我发现@givanse辉煌的答案是最可靠和兼容跨多个移动浏览器注册刷卡行动。

但是,在使用jQuery现代移动浏览器中使其工作的代码发生了变化。

如果使用jQuery event.touches将不存在,并导致undefined ,应由event.originalEvent.touchesreplace。 没有jQueryevent.touches应该可以正常工作。

所以解决scheme变成了,

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

testing:

  • Android :Chrome,UC浏览器
  • iOS :Safari,Chrome,UC浏览器

我已经重新包装TouchWipe作为一个简短的jQuery插件: detectSwipe

一些最热门的回答(无法评论…)来处理短的滑动

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

如果有人试图在Android上使用jQuery Mobile,并且在使用JQM轻扫检测时遇到问题

(我有一些Xperia Z1,Galaxy S3,Nexus 4和一些Wiko手机),这可能是有用的:

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

除非是非常长,精确和快速的滑动,否则不会检测到在Android上滑动。

有了这两条线,它工作正常

trashold,超时刷卡,swipeBlockElems添加。

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

当用户拖动手指时,我不断地触发touchend handler。 我不知道这是由于我做错了什么,但我重新接线这个积累touchmove和touchend移动实际上触发callback。

我还需要有大量的这些实例,所以我添加了启用/禁用方法。

而短的轻扫不会触发的阈值。 每次触摸启动零计数器。

您可以即时更改target_node。 启用创build是可选的。

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

使用二:

jQuery mobile:在绝大多数情况下工作,特别是在开发使用其他jQuery插件的应用程序时,最好使用jQuery移动控件。 访问它在这里: https : //www.w3schools.com/jquerymobile/jquerymobile_events_touch.asp

锤子时间! 最好的,轻量级和快速的基于JavaScript的库之一。 访问它在这里: https : //hammerjs.github.io/