如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
当前回答
我发现@givanse的答案是最可靠和最兼容的多个移动浏览器,用于注册滑动操作。
但是,他的代码需要做一些更改,才能在使用jQuery的现代移动浏览器中工作。
事件。如果使用jQuery并且结果为undefined, touches将不存在,应该由event. originalevent . touches_替换。没有jQuery,事件。触摸应该可以正常工作。
所以解就是,
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;
};
测试:
Android: Chrome, UC浏览器 iOS: Safari, Chrome, UC浏览器
其他回答
首先使用鼠标事件原型实现它可能会更容易一些。
这里有很多答案,包括顶部,应该谨慎使用,因为它们不考虑边界情况,特别是在边界框周围。
See:
触摸事件 鼠标事件
你需要尝试捕捉边缘情况和行为,比如指针在结束前移动到元素之外。
滑动是一种非常基本的手势,它是一种更高级别的界面指针交互处理,大致介于处理原始事件和手写识别之间。
没有一种确切的方法来检测滑动或投掷,尽管几乎所有方法都遵循一个基本原则,即通过距离和速度或速度的阈值来检测元素的运动。你可以简单地说,如果在给定的时间内,在给定的方向上有65%的屏幕大小的移动,那么这就是一次滑动。具体在哪里划定界限以及如何计算取决于你自己。
有些人可能还会从某个方向的动量角度以及元素释放时它被推离屏幕的距离来看待它。这是更清晰的粘滞滑动,元素可以拖动,然后释放,要么反弹,要么飞出屏幕,就像弹性断裂。
最好是找到一个手势库,你可以移植或重用,通常用于一致性。这里的许多例子都过于简单,将滑动记录为任何方向上最轻微的触摸。
Android将是显而易见的选择,尽管它有相反的问题,它过于复杂。
许多人似乎把这个问题误解为某个方向的任何运动。滑动是一种面向单一方向的广泛且相对简短的运动(尽管可能是弧形的并具有一定的加速属性)。抛掷是类似的,但它是指在自身动量的作用下,随意地将物体推离一定距离。
这两者非常相似,以至于一些库可能只提供可以互换使用的fling或swipe。在平面屏幕上,很难真正区分这两种手势,一般来说,人们都在做这两种动作(滑动物理屏幕,但投掷屏幕上显示的UI元素)。
你最好的选择就是不要自己动手。目前已经有大量用于检测简单手势的JavaScript库。
如果你只需要滑动,你最好只使用你需要的部分。 这应该适用于任何触摸设备。
这是经过gzip压缩,缩小,babel等大约450字节。
我根据其他答案编写了下面的类,它使用移动百分比而不是像素,以及一个事件分派器模式来挂钩/取消挂钩。
像这样使用它:
const dispatcher = new SwipeEventDispatcher(myElement);
dispatcher.on('SWIPE_RIGHT', () => { console.log('I swiped right!') })
export class SwipeEventDispatcher { constructor(element, options = {}) { this.evtMap = { SWIPE_LEFT: [], SWIPE_UP: [], SWIPE_DOWN: [], SWIPE_RIGHT: [] }; this.xDown = null; this.yDown = null; this.element = element; this.options = Object.assign({ triggerPercent: 0.3 }, options); element.addEventListener('touchstart', evt => this.handleTouchStart(evt), false); element.addEventListener('touchend', evt => this.handleTouchEnd(evt), false); } on(evt, cb) { this.evtMap[evt].push(cb); } off(evt, lcb) { this.evtMap[evt] = this.evtMap[evt].filter(cb => cb !== lcb); } trigger(evt, data) { this.evtMap[evt].map(handler => handler(data)); } handleTouchStart(evt) { this.xDown = evt.touches[0].clientX; this.yDown = evt.touches[0].clientY; } handleTouchEnd(evt) { const deltaX = evt.changedTouches[0].clientX - this.xDown; const deltaY = evt.changedTouches[0].clientY - this.yDown; const distMoved = Math.abs(Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : deltaY); const activePct = distMoved / this.element.offsetWidth; if (activePct > this.options.triggerPercent) { if (Math.abs(deltaX) > Math.abs(deltaY)) { deltaX < 0 ? this.trigger('SWIPE_LEFT') : this.trigger('SWIPE_RIGHT'); } else { deltaY > 0 ? this.trigger('SWIPE_UP') : this.trigger('SWIPE_DOWN'); } } } } export default SwipeEventDispatcher;
我之前使用的方法是,您必须检测mousedown事件,记录其x,y位置(任何相关的位置),然后检测mouseup事件,并减去两个值。
根据@givanse的回答,以下是你可以用类来做的:
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!");
});