gru*_*gru 16 html javascript mobile event-handling reactjs
我目前正在开发一个 React 应用程序,我想检测元素div(在移动设备上)上的滑动事件(左、右)。
在没有任何额外库的情况下如何实现这一目标?
gru*_*gru 41
此代码检测左右滑动事件,不会对通常的触摸事件产生任何影响。
const [touchStart, setTouchStart] = useState(null)
const [touchEnd, setTouchEnd] = useState(null)
// the required distance between touchStart and touchEnd to be detected as a swipe
const minSwipeDistance = 50
const onTouchStart = (e) => {
setTouchEnd(null) // otherwise the swipe is fired even with usual touch events
setTouchStart(e.targetTouches[0].clientX)
}
const onTouchMove = (e) => setTouchEnd(e.targetTouches[0].clientX)
const onTouchEnd = () => {
if (!touchStart || !touchEnd) return
const distance = touchStart - touchEnd
const isLeftSwipe = distance > minSwipeDistance
const isRightSwipe = distance < -minSwipeDistance
if (isLeftSwipe || isRightSwipe) console.log('swipe', isLeftSwipe ? 'left' : 'right')
// add your conditional logic here
}
Run Code Online (Sandbox Code Playgroud)
<div onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}/>
Run Code Online (Sandbox Code Playgroud)
如果您还需要检测垂直滑动(向上和向下),您可以以类似的方式使用e.targetTouches[0].clientY(请参阅文档)。
E L*_*E L 10
@gru 提供的优秀解决方案。我只是将其封装到自定义挂钩中,以便更简单地在不同组件之间集成。
useSwipe.tsx
import {TouchEvent, useState} from "react";
interface SwipeInput {
onSwipedLeft: () => void
onSwipedRight: () => void
}
interface SwipeOutput {
onTouchStart: (e: TouchEvent) => void
onTouchMove: (e: TouchEvent) => void
onTouchEnd: () => void
}
export default (input: SwipeInput): SwipeOutput => {
const [touchStart, setTouchStart] = useState(0);
const [touchEnd, setTouchEnd] = useState(0);
const minSwipeDistance = 50;
const onTouchStart = (e: TouchEvent) => {
setTouchEnd(0); // otherwise the swipe is fired even with usual touch events
setTouchStart(e.targetTouches[0].clientX);
}
const onTouchMove = (e: TouchEvent) => setTouchEnd(e.targetTouches[0].clientX);
const onTouchEnd = () => {
if (!touchStart || !touchEnd) return;
const distance = touchStart - touchEnd;
const isLeftSwipe = distance > minSwipeDistance;
const isRightSwipe = distance < -minSwipeDistance;
if (isLeftSwipe) {
input.onSwipedLeft();
}
if (isRightSwipe) {
input.onSwipedRight();
}
}
return {
onTouchStart,
onTouchMove,
onTouchEnd
}
}
Run Code Online (Sandbox Code Playgroud)
可以像这样集成到不同的组件中
import useSwipe from "whatever-path/useSwipe";const swipeHandlers = useSwipe({ onSwipedLeft: () => console.log('left'), onSwipedRight: () => console.log('right') });<div {...swipeHandlers}>some swipeable div (or whatever html tag)</div>@gru 的代码工作得很好,唯一的缺点是,当用户尝试向下滚动并稍微向一侧移动时,它还会检测到滑动。
我的更改确保仅当水平移动大于垂直移动时才检测到滑动:
const distanceX = touchStartX - touchEndX
const distanceY = touchStartY - touchEndY
const isLeftSwipe = distanceX > minSwipeDistance
const isRightSwipe = distanceX < -minSwipeDistance
if (isRightSwipe && Math.abs(distanceX) > distanceY) {
// add your conditional logic here
}
if (isLeftSwipe && distanceX > distanceY) {
// add your conditional logic here
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26464 次 |
| 最近记录: |