简体   繁体   English

我如何识别 React 中的滑动事件?

[英]How do I recognize swipe events in React?

I'm currently developing a React app and I want to detect swipe events (left, right) on a div element (on mobile devices).我目前正在开发一个 React 应用程序,我想检测div元素(在移动设备上)上的滑动事件(左、右)。

How do I achieve this without any additional libraries?我如何在没有任何额外库的情况下实现这一目标?

@gru's code works great, the only downside is that it also detects a swipe when the user tries to scroll down and moves slightly to the side as well. @gru 的代码运行良好,唯一的缺点是当用户尝试向下滚动并稍微向侧面移动时,它也会检测到滑动。

My changes makes sure the swipe is only detected when the horizontal movement is greater than the vertical movement:我的更改确保仅当水平移动大于垂直移动时才检测到滑动:

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
}

Horiziontal swipes (left, right)水平滑动(左,右)

This code detects left and right swipe events, without having any impact on usual touch events.此代码检测左右滑动事件,对通常的触摸事件没有任何影响。

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}/>

Vertical swipes (up, down)垂直滑动(上、下)

If you need to detect vertical swipes as well (up and down), you can use e.targetTouches[0].clientY (see docs ) in a similar manner.如果您还需要检测垂直滑动(向上和向下),您可以以类似的方式使用e.targetTouches[0].clientY (请参阅 文档)。

Excellent solution provided by @gru. @gru 提供的优秀解决方案。 I just encapsulated it into a custom hook to be simpler to integrate between different components.我只是将它封装到一个自定义挂钩中,以便更简单地在不同组件之间进行集成。

useSwipe.tsx使用滑动.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
    }
}

can be integrated in different components like this可以像这样集成在不同的组件中

  1. import useSwipe from "whatever-path/useSwipe";
  2. const swipeHandlers = useSwipe({ onSwipedLeft: () => console.log('left'), onSwipedRight: () => console.log('right') });
  3. <div {...swipeHandlers}>some swipeable div (or whatever html tag)</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM