如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
当前回答
我之前使用的方法是,您必须检测mousedown事件,记录其x,y位置(任何相关的位置),然后检测mouseup事件,并减去两个值。
其他回答
我之前使用的方法是,您必须检测mousedown事件,记录其x,y位置(任何相关的位置),然后检测mouseup事件,并减去两个值。
一个如何使用偏移量的例子。
// at least 100 px are a swipe // you can use the value relative to screen size: window.innerWidth * .1 const offset = 100; let xDown, yDown window.addEventListener('touchstart', e => { const firstTouch = getTouch(e); xDown = firstTouch.clientX; yDown = firstTouch.clientY; }); window.addEventListener('touchend', e => { if (!xDown || !yDown) { return; } const { clientX: xUp, clientY: yUp } = getTouch(e); const xDiff = xDown - xUp; const yDiff = yDown - yUp; const xDiffAbs = Math.abs(xDown - xUp); const yDiffAbs = Math.abs(yDown - yUp); // at least <offset> are a swipe if (Math.max(xDiffAbs, yDiffAbs) < offset ) { return; } if (xDiffAbs > yDiffAbs) { if ( xDiff > 0 ) { console.log('left'); } else { console.log('right'); } } else { if ( yDiff > 0 ) { console.log('up'); } else { console.log('down'); } } }); function getTouch (e) { return e.changedTouches[0] }
如果你只需要滑动,你最好只使用你需要的部分。 这应该适用于任何触摸设备。
这是经过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;
我发现@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浏览器
根据@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();