如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
当前回答
再加上这个答案。这个增加了对鼠标事件的支持,用于桌面测试:
<!--scripts-->
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.isMouseDown = false;
this.listenForMouseEvents = true;
this.options = Object.assign({ triggerPercent: 0.3 }, options);
element.addEventListener('touchstart', evt => this.handleTouchStart(evt), false);
element.addEventListener('touchend', evt => this.handleTouchEnd(evt), false);
element.addEventListener('mousedown', evt => this.handleMouseDown(evt), false);
element.addEventListener('mouseup', evt => this.handleMouseUp(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;
}
handleMouseDown(evt) {
if (this.listenForMouseEvents==false) return;
this.xDown = evt.clientX;
this.yDown = evt.clientY;
this.isMouseDown = true;
}
handleMouseUp(evt) {
if (this.isMouseDown == false) return;
const deltaX = evt.clientX - this.xDown;
const deltaY = evt.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');
}
}
}
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');
}
}
}
}
// add a listener on load
window.addEventListener("load", function(event) {
const dispatcher = new SwipeEventDispatcher(document.body);
dispatcher.on('SWIPE_RIGHT', () => { console.log('I swiped right!') })
dispatcher.on('SWIPE_LEFT', () => { console.log('I swiped left!') })
});
其他回答
在这里的建议之上,我将跟踪手指号码,因为如果你同时用两个手指触摸,它将获得X位置,而不会导致一个奇怪的行为,而且,你可能想要设置一个“距离”最小值,这样用户在通过你的网站或应用程序触摸时就不会错误地触发滑动。
//Swipe
let touchstartX = 0
let touchendX = 0
let fingerCount = 0
const checkDirection = () => {
const distance = 50 //Minimum distance for the swipe to work
//left
if (touchendX < touchstartX && (touchstartX - touchendX) > distance ){
//Do something cool
}
//right
if (touchendX > touchstartX && (touchendX - touchstartX) > distance){
//Do something cooler
}
document.addEventListener('touchstart', e => {
fingerCount = e.touches.length
touchstartX = e.changedTouches[0].clientX
})
document.addEventListener('touchend', e => {
touchendX = e.changedTouches[0].clientX
if(fingerCount === 1){
checkDirection()
}
})
简单的JS代码示例:
document.addEventListener('touchstart', handleTouchStart, false);
document.addEventListener('touchmove', handleTouchMove, false);
var xDown = null;
var yDown = null;
function getTouches(evt) {
return evt.touches || // browser API
evt.originalEvent.touches; // jQuery
}
function handleTouchStart(evt) {
const firstTouch = getTouches(evt)[0];
xDown = firstTouch.clientX;
yDown = firstTouch.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 ) {
/* right swipe */
} else {
/* left swipe */
}
} else {
if ( yDiff > 0 ) {
/* down swipe */
} else {
/* up swipe */
}
}
/* reset values */
xDown = null;
yDown = null;
};
Android测试。
简单的水平滑动JS示例:
let touchstartX = 0
let touchendX = 0
function checkDirection() {
if (touchendX < touchstartX) alert('swiped left!')
if (touchendX > touchstartX) alert('swiped right!')
}
document.addEventListener('touchstart', e => {
touchstartX = e.changedTouches[0].screenX
})
document.addEventListener('touchend', e => {
touchendX = e.changedTouches[0].screenX
checkDirection()
})
垂直滑动也可以使用相同的逻辑。
我将这里的一些答案合并到一个脚本中,该脚本使用CustomEvent在DOM中触发滑动事件。添加0.7k的swiped-events.min.js脚本到你的页面,并监听滑动事件:
刷卡
document.addEventListener('swiped', function(e) {
console.log(e.target); // the element that was swiped
console.log(e.detail.dir); // swiped direction
});
swiped-left
document.addEventListener('swiped-left', function(e) {
console.log(e.target); // the element that was swiped
});
swiped-right
document.addEventListener('swiped-right', function(e) {
console.log(e.target); // the element that was swiped
});
swiped-up
document.addEventListener('swiped-up', function(e) {
console.log(e.target); // the element that was swiped
});
swiped-down
document.addEventListener('swiped-down', function(e) {
console.log(e.target); // the element that was swiped
});
你也可以直接附加到一个元素:
document.getElementById('myBox').addEventListener('swiped-down', function(e) {
console.log(e.target); // the element that was swiped
});
可选配置
您可以指定以下属性来调整页面中的滑动交互功能(这些是可选的)。
<div data-swipe-threshold="10"
data-swipe-timeout="1000"
data-swipe-ignore="false">
Swiper, get swiping!
</div>
要在应用程序范围内设置默认值,请在最顶部的元素上设置配置属性:
<body data-swipe-threshold="100" data-swipe-timeout="250">
<div>Swipe me</div>
<div>or me</div>
</body>
源代码可在Github
一些mod的顶部回答(不能评论…)来处理短滑动
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;
}
};