use-gesture官方文档详解:从入门到精通

use-gesture官方文档详解:从入门到精通

【免费下载链接】use-gesture 👇Bread n butter utility for component-tied mouse/touch gestures in React and Vanilla Javascript. 【免费下载链接】use-gesture 项目地址: https://gitcode.com/gh_mirrors/us/use-gesture

引言

你还在为实现流畅的触摸和鼠标手势交互而烦恼吗?use-gesture是一个功能强大的JavaScript库,它能帮助你轻松地为React和Vanilla JavaScript应用添加丰富的手势支持。无论是拖拽、缩放、滑动还是旋转,use-gesture都能提供简洁而强大的API,让你的应用交互体验提升到新的水平。

读完本文,你将能够:

  • 了解use-gesture的核心概念和架构
  • 掌握在React和Vanilla JavaScript中使用各种手势的方法
  • 学会配置手势选项以满足特定需求
  • 解决常见的手势交互问题
  • 探索实用的示例和最佳实践

什么是use-gesture?

use-gesture是一个轻量级的手势库,它允许你将鼠标和触摸事件绑定到任何组件或元素上。通过提供丰富的手势数据,use-gesture使得实现复杂的交互效果变得简单,通常只需几行代码。

use-gesture示例

use-gesture最初是为React构建的,但从v10版本开始,它已经成为平台无关的库,可以在Vanilla JavaScript中使用。你可以将其单独使用,也可以与动画库(如react-spring)结合使用,以创建更加流畅的交互体验。

官方文档:documentation/pages/docs/introduction.mdx 项目源码:packages/ 项目教程:README.md

安装与基本使用

安装

use-gesture提供了两个包:一个用于React,一个用于Vanilla JavaScript。

React安装:

# Yarn
yarn add @use-gesture/react

# NPM
npm install @use-gesture/react

Vanilla JavaScript安装:

# Yarn
yarn add @use-gesture/vanilla

# NPM
npm install @use-gesture/vanilla

基本示例

React示例:

import { useSpring, animated } from '@react-spring/web'
import { useDrag } from '@use-gesture/react'

function PullRelease() {
  const [{ x, y }, api] = useSpring(() => ({ x: 0, y: 0 }))

  // 设置拖动钩子并根据手势数据定义组件移动
  const bind = useDrag(({ down, movement: [mx, my] }) => {
    api.start({ x: down ? mx : 0, y: down ? my : 0, immediate: down })
  })

  // 将其绑定到组件
  return <animated.div {...bind()} style={{ x, y, touchAction: 'none' }} />
}

Vanilla JavaScript示例:

<!-- index.html -->
<div id="drag" />
// script.js
const el = document.getElementById('drag')
const gesture = new DragGesture(el, ({ active, movement: [mx, my] }) => {
  setActive(active)
  anime({
    targets: el,
    translateX: active ? mx : 0,
    translateY: active ? my : 0,
    duration: active ? 0 : 1000
  })
})

// 当你想移除监听器时
gesture.destroy()

这个简单的例子创建了一个可拖动的元素,它会跟随鼠标或触摸移动,并在释放时返回初始位置。

重要提示:在可拖动元素上,你应该始终使用CSS属性touch-action: none,以防止在触摸设备上与浏览器原生滚动发生冲突。

支持的手势类型

use-gesture提供了多种手势钩子(React)和类(Vanilla),以处理不同类型的用户交互。

React手势钩子

钩子名称描述
useDrag处理拖拽手势
useMove处理鼠标移动事件
useHover处理鼠标进入和离开事件
useScroll处理滚动事件
useWheel处理鼠标滚轮事件
usePinch处理捏合手势(缩放和旋转)
useGesture在一个钩子中处理多种手势

Vanilla JavaScript手势类

类名称描述
DragGesture处理拖拽手势
MoveGesture处理鼠标移动事件
HoverGesture处理鼠标进入和离开事件
ScrollGesture处理滚动事件
WheelGesture处理鼠标滚轮事件
PinchGesture处理捏合手势(缩放和旋转)
Gesture在一个类中处理多种手势

手势源码:packages/core/src/engines/

手势状态

每次手势处理器被调用时,它都会收到一个手势状态对象,其中包含源事件和多个附加属性,如速度先前值等。

通用手势状态属性

const bind = useDrag(state => {
  const {
    event,         // 源事件
    xy,            // [x,y] 值(指针位置或滚动偏移)
    initial,       // 手势开始时的xy值
    intentional,   // 手势是否是有意的
    delta,         // 移动增量(当前移动 - 上一次移动)
    offset,        // 自第一次手势以来的偏移量
    lastOffset,    // 上一次手势开始时的偏移量
    movement,      // offset与lastOffset之间的位移
    velocity,      // 手势在每个轴上的动量(以px/ms为单位)
    distance,      // 每个轴上的偏移距离
    direction,     // 每个轴上的方向
    overflow,      // 偏移是否超出边界(每个轴)
    startTime,     // 手势开始时间(ms)
    timeDelta,     // 与上一个事件的时间差(ms)
    elapsedTime,   // 手势经过的时间(ms)
    timeStamp,     // 事件的时间戳
    type,          // 事件类型
    target,        // 事件目标
    currentTarget, // 事件当前目标
    first,         // 是否是第一个事件
    last,          // 是否是最后一个事件
    active,        // 手势是否处于活动状态
    memo,          // 处理器上一次运行返回的值
    cancel,        // 可以调用以中断某些手势的函数
    canceled,      // 手势是否被取消(拖拽和捏合)
    down,          // 鼠标按钮或触摸是否按下
    buttons,       // 按下的按钮数量
    touches,       // 触摸屏幕的手指数量
    args,          // 传递给bind的参数(仅React)
    ctrlKey,       // Ctrl键是否按下
    altKey,        // Alt键是否按下
    shiftKey,      // Shift键是否按下
    metaKey,       // Meta键是否按下
    locked,        // document.pointerLockElement是否设置
    dragging,      // 组件当前是否被拖拽
    moving,        // 组件当前是否被移动
    scrolling,     // 组件当前是否被滚动
    wheeling,      // 组件当前是否被滚轮操作
    pinching       // 组件当前是否被捏合
  } = state
})

捏合手势特有属性

捏合手势的状态属性包括上述所有属性(除了xyvxvy),并添加了以下属性:

const bind = usePinch(state => {
  const {
    da,            // 两个指针的绝对距离和角度 [distance, angle]
    origin,        // 两个触摸事件之间的中心点坐标
    offset,        // [scale, angle] 偏移量(以scale=1开始)
  } = state
})

拖拽手势特有属性

拖拽手势状态添加了一些有助于理解用户意图的属性:

const bind = useDrag(state => {
  const {
    swipe,         // [swipeX, swipeY] 如果未检测到滑动则为0,否则为-1或1
    tap,           // 拖拽是否被识别为点击
  } = state
})

状态类型定义:packages/core/src/types/state.ts

手势配置选项

use-gesture提供了多种选项来配置手势行为。这些选项可以分为共享选项和特定手势选项。

配置对象结构

根据你使用的是特定手势钩子还是useGesture钩子/Gesture类,配置对象的结构会有所不同。

React示例:

// 使用特定手势钩子时
useDrag((state) => doSomethingWith(state), { ...sharedOptions, ...dragOptions })

// 使用useGesture钩子时
useGesture(
  {
    onDrag: (state) => doSomethingWith(state),
    onPinch: (state) => doSomethingWith(state)
    // ...
  },
  {
    // 全局选项,如`target`
    ...sharedOptions,
    // 特定手势选项
    drag: dragOptions,
    wheel: wheelOptions,
    pinch: pinchOptions,
    scroll: scrollOptions,
    hover: hoverOptions
  }
)

常用配置选项

选项名称适用手势描述
enabled所有是否启用手势
axis坐标类限制手势只能在指定轴上触发('x'、'y'、'lock'或undefined)
threshold所有手势位移必须大于此阈值才会触发处理器
bounds坐标类将手势偏移限制在指定边界内
from所有指定偏移量的起始位置
preventDefault所有是否阻止事件的默认行为
touchAction拖拽CSS touch-action属性,用于优化触摸设备上的交互
filterTaps拖拽是否过滤点击事件,区分点击和拖拽
swipe.distance拖拽触发滑动所需的最小距离
swipe.velocity拖拽触发滑动所需的最小速度

示例:限制拖拽边界

const bind = useDrag(
  ({ offset: [ox, oy] }) => api.start({ x: ox, y: oy }),
  { bounds: { left: -100, right: 100, top: -50, bottom: 50 } }
)

示例:设置滑动检测阈值

const bind = useDrag(
  ({ swipe }) => {
    if (swipe[0] !== 0) {
      console.log('水平滑动:', swipe[0] === 1 ? '右' : '左')
    }
  },
  { swipe: { distance: 50, velocity: 0.5 } }
)

完整选项说明:documentation/pages/docs/options.mdx

高级用法

同时处理多种手势

use-gesture允许你在同一个组件上同时处理多种手势。例如,你可能希望在同一个组件上启用拖拽和捏合手势。

import { useGesture } from '@use-gesture/react'

const bind = useGesture({
  onDrag: (state) => handleDrag(state),
  onPinch: (state) => handlePinch(state),
  onWheel: (state) => handleWheel(state),
  // 其他手势...
}, {
  drag: { axis: 'x' },
  pinch: { scaleBounds: { min: 0.5, max: 3 } },
  wheel: { preventDefault: true }
})

return <div {...bind()} />

自定义手势识别器

如果你只需要使用部分手势,可以创建自定义的手势识别器,以减小 bundle 体积。

import { createUseGesture, dragAction, pinchAction } from '@use-gesture/react'

// 只包含拖拽和捏合手势
const useGesture = createUseGesture([dragAction, pinchAction])

const bind = useGesture({
  onDrag: (state) => doSomethingWith(state),
  onPinch: (state) => doSomethingWith(state)
}, {
  drag: dragConfig,
  pinch: pinchConfig
})

return <div {...bind()} />

自定义手势源码:packages/react/src/createUseGesture.ts

使用ref绑定手势

在某些情况下,你可能需要将手势绑定到不是直接子组件的元素上。这时可以使用target选项和React ref。

import { useRef } from 'react'

function RefExample() {
  const ref = useRef()
  const bind = useDrag((state) => doSomethingWith(state), { target: ref })
  
  return (
    <div>
      <div ref={ref}>这个元素会接收手势事件</div>
      <div>这个元素不会</div>
    </div>
  )
}

实际示例

use-gesture可以用于创建各种复杂的交互效果。以下是一些常见的示例:

1. 可拖拽列表

可拖拽列表示例

这个示例展示了如何创建一个可拖拽排序的列表。关键在于使用拖拽手势的offsetargs属性来跟踪每个列表项的位置变化。

源码示例:demo/src/sandboxes/draggable-list/

2. 卡片堆叠

卡片堆叠示例

这个示例展示了一个类似Tinder的卡片堆叠交互,使用拖拽手势的directionvelocity属性来判断卡片的滑动方向和速度,从而决定卡片是被接受还是拒绝。

源码示例:demo/src/sandboxes/cards-stack/

3. 无限轮播

无限轮播示例

这个示例结合了拖拽和滚轮手势来创建一个无限轮播组件。使用movement属性来跟踪滑动距离,使用wheel事件来响应用户的滚轮操作。

源码示例:demo/src/sandboxes/infinite-slideshow/

更多示例:documentation/pages/docs/examples.mdx

常见问题与解决方案

Q: 如何区分点击和拖拽事件?

A: 使用filterTaps选项可以帮助区分点击和拖拽。当设置filterTaps: true时,轻微的点击不会触发拖拽逻辑,并且state.tap会在点击时为true

const bind = useDrag(
  ({ tap, down, movement }) => {
    if (tap) {
      console.log('点击事件')
    } else if (down) {
      console.log('拖拽中', movement)
    }
  },
  { filterTaps: true }
)

Q: 如何在移动设备上防止页面滚动?

A: 使用CSS的touch-action属性可以优化触摸设备上的交互。例如,touch-action: pan-y允许垂直滚动,但阻止水平滚动,这在处理水平拖拽时很有用。

return <div {...bind()} style={{ touchAction: 'pan-y' }} />

Q: 为什么我的拖拽元素在移动设备上响应迟缓?

A: 这可能是因为没有正确设置touch-action属性,导致浏览器的默认触摸行为与你的拖拽逻辑冲突。确保为拖拽元素设置touch-action: none

.draggable-element {
  touch-action: none;
  user-select: none; /* 可选,防止文本选择 */
}

更多常见问题:documentation/pages/docs/faq.mdx

性能优化

使用事件委托

对于大量相似元素(如列表项),使用事件委托可以提高性能。use-gesture的target选项允许你将事件监听器附加到父元素,而不是每个子元素。

避免不必要的渲染

当使用React时,尽量避免在手势处理器中触发不必要的渲染。可以使用useCallback记忆化处理器函数,或使用react-spring等动画库直接操作DOM,而不经过React的渲染周期。

合理设置阈值

为手势设置适当的threshold可以防止微小的无意移动触发手势逻辑,提高用户体验并减少不必要的计算。

总结

use-gesture是一个功能强大且灵活的手势库,它简化了在React和Vanilla JavaScript应用中实现复杂手势交互的过程。通过提供丰富的手势数据和可配置的选项,use-gesture使开发者能够轻松创建流畅、自然的用户交互。

无论是简单的拖拽功能还是复杂的多点触控操作,use-gesture都能满足你的需求。其简洁的API设计和详细的文档使学习和使用过程变得轻松愉快。

进一步学习资源

现在,你已经掌握了use-gesture的核心概念和使用方法,是时候将这些知识应用到你的项目中,为用户创造更加丰富和直观的交互体验了!

【免费下载链接】use-gesture 👇Bread n butter utility for component-tied mouse/touch gestures in React and Vanilla Javascript. 【免费下载链接】use-gesture 项目地址: https://gitcode.com/gh_mirrors/us/use-gesture

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值