如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
如何检测用户用JavaScript在网页上向某个方向滑动手指?
我想知道是否有一种解决方案可以同时适用于iPhone和Android手机上的网站。
当前回答
一些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;
}
};
其他回答
如果你只需要滑动,你最好只使用你需要的部分。 这应该适用于任何触摸设备。
这是经过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;
我必须为旋转木马编写一个简单的脚本,以检测向左或向右的滑动。
我使用指针事件代替触摸事件。
我希望这对个人有用,我欢迎任何改进我的代码的见解;我觉得很不好意思加入这个线程与显著优秀的JS开发人员。
function getSwipeX({elementId}) {
this.e = document.getElementsByClassName(elementId)[0];
this.initialPosition = 0;
this.lastPosition = 0;
this.threshold = 200;
this.diffInPosition = null;
this.diffVsThreshold = null;
this.gestureState = 0;
this.getTouchStart = (event) => {
event.preventDefault();
if (window.PointerEvent) {
this.e.setPointerCapture(event.pointerId);
}
return this.initalTouchPos = this.getGesturePoint(event);
}
this.getTouchMove = (event) => {
event.preventDefault();
return this.lastPosition = this.getGesturePoint(event);
}
this.getTouchEnd = (event) => {
event.preventDefault();
if (window.PointerEvent) {
this.e.releasePointerCapture(event.pointerId);
}
this.doSomething();
this.initialPosition = 0;
}
this.getGesturePoint = (event) => {
this.point = event.pageX
return this.point;
}
this.whatGestureDirection = (event) => {
this.diffInPosition = this.initalTouchPos - this.lastPosition;
this.diffVsThreshold = Math.abs(this.diffInPosition) > this.threshold;
(Math.sign(this.diffInPosition) > 0) ? this.gestureState = 'L' : (Math.sign(this.diffInPosition) < 0) ? this.gestureState = 'R' : this.gestureState = 'N';
return [this.diffInPosition, this.diffVsThreshold, this.gestureState];
}
this.doSomething = (event) => {
let [gestureDelta,gestureThreshold,gestureDirection] = this.whatGestureDirection();
// USE THIS TO DEBUG
console.log(gestureDelta,gestureThreshold,gestureDirection);
if (gestureThreshold) {
(gestureDirection == 'L') ? // LEFT ACTION : // RIGHT ACTION
}
}
if (window.PointerEvent) {
this.e.addEventListener('pointerdown', this.getTouchStart, true);
this.e.addEventListener('pointermove', this.getTouchMove, true);
this.e.addEventListener('pointerup', this.getTouchEnd, true);
this.e.addEventListener('pointercancel', this.getTouchEnd, true);
}
}
可以使用new调用该函数。
window.addEventListener('load', () => {
let test = new getSwipeX({
elementId: 'your_div_here'
});
})
我重做了@givanse的解决方案,使其发挥React钩子的作用。输入是一些可选的事件监听器,输出是一个功能性的ref(需要是功能性的,以便当/如果ref改变时钩子可以重新运行)。
还添加了垂直/水平滑动阈值参数,这样小的运动不会意外触发事件监听器,但这些可以设置为0,以更接近地模拟原始答案。
提示:为了获得最佳性能,应该记住事件侦听器输入函数。
function useSwipeDetector({
// Event listeners.
onLeftSwipe,
onRightSwipe,
onUpSwipe,
onDownSwipe,
// Threshold to detect swipe.
verticalSwipeThreshold = 50,
horizontalSwipeThreshold = 30,
}) {
const [domRef, setDomRef] = useState(null);
const xDown = useRef(null);
const yDown = useRef(null);
useEffect(() => {
if (!domRef) {
return;
}
function handleTouchStart(evt) {
const [firstTouch] = evt.touches;
xDown.current = firstTouch.clientX;
yDown.current = firstTouch.clientY;
};
function handleTouchMove(evt) {
if (!xDown.current || !yDown.current) {
return;
}
const [firstTouch] = evt.touches;
const xUp = firstTouch.clientX;
const yUp = firstTouch.clientY;
const xDiff = xDown.current - xUp;
const yDiff = yDown.current - yUp;
if (Math.abs(xDiff) > Math.abs(yDiff)) {/*most significant*/
if (xDiff > horizontalSwipeThreshold) {
if (onRightSwipe) onRightSwipe();
} else if (xDiff < -horizontalSwipeThreshold) {
if (onLeftSwipe) onLeftSwipe();
}
} else {
if (yDiff > verticalSwipeThreshold) {
if (onUpSwipe) onUpSwipe();
} else if (yDiff < -verticalSwipeThreshold) {
if (onDownSwipe) onDownSwipe();
}
}
};
function handleTouchEnd() {
xDown.current = null;
yDown.current = null;
}
domRef.addEventListener("touchstart", handleTouchStart, false);
domRef.addEventListener("touchmove", handleTouchMove, false);
domRef.addEventListener("touchend", handleTouchEnd, false);
return () => {
domRef.removeEventListener("touchstart", handleTouchStart);
domRef.removeEventListener("touchmove", handleTouchMove);
domRef.removeEventListener("touchend", handleTouchEnd);
};
}, [domRef, onLeftSwipe, onRightSwipe, onUpSwipe, onDownSwipe, verticalSwipeThreshold, horizontalSwipeThreshold]);
return (ref) => setDomRef(ref);
};
我将这里的一些答案合并到一个脚本中,该脚本使用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
简单的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测试。