我目前正在开发一个React应用程序,我想检测div元素(在移动的设备上)上的滑动事件(左,右)。如何在没有任何额外库的情况下实现这一点?
div
pxyaymoc1#
此代码检测左右滑动事件,而不会对通常的触摸事件产生任何影响。
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 }
<div onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}/>
如果您还需要检测垂直滑动(向上和向下),您可以以类似的方式使用e.targetTouches[0].clientY(请参阅docs)。
e.targetTouches[0].clientY
piztneat2#
@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 }
htzpubme3#
@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 } }
可以像这样集成在不同的组件中
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>
xurqigkl4#
受dear gru的answer的启发,我将其改编为React Native。代码如下。(它会找到垂直距离,将pageY更改为pageX也会找到水平距离)
const [touchStart, setTouchStart] = useState(null); const [touchEnd, setTouchEnd] = useState(null); const minSwipeDistance = 50; const onTouchStart = (e) => { setTouchEnd(null); setTouchStart(e.nativeEvent.touches[0].pageY); } const onTouchMove = (e) => { setTouchEnd(e.nativeEvent.touches[0].pageY); } const onTouchEnd = () => { if (!touchStart || !touchEnd) return; if (touchStart - touchEnd > minSwipeDistance) { // Do something } } <View onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd} > ... </View>
4条答案
按热度按时间pxyaymoc1#
水平滑动(左、右)
此代码检测左右滑动事件,而不会对通常的触摸事件产生任何影响。
垂直滑动(上下)
如果您还需要检测垂直滑动(向上和向下),您可以以类似的方式使用
e.targetTouches[0].clientY
(请参阅docs)。piztneat2#
@gru的代码工作得很好,唯一的缺点是,当用户试图向下滚动时,它也会检测到滑动,并且也会稍微移动到侧面。
我的更改确保仅当水平移动大于垂直移动时才检测到滑动:
htzpubme3#
@gru提供的优秀解决方案。我只是将其封装到一个自定义钩子中,以便更容易在不同组件之间集成。
useSwipe.tsx
可以像这样集成在不同的组件中
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>
xurqigkl4#
受dear gru的answer的启发,我将其改编为React Native。代码如下。(它会找到垂直距离,将pageY更改为pageX也会找到水平距离)