【入门】@use-gesture 手势交互框架

2,316 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

介绍

参考: @use-gesture

  1. 可以将鼠标和触摸事件绑定到任何节点
  2. 提供了多个钩子函数
  3. 可以单独使用,但是建议和 [[@react-spring 弹簧动画框架]] 等动画库结合

安装

npm install @use-gesture/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 }))

  // Set the drag hook and define component movement based on gesture data
  const bind = useDrag(({ down, movement: [mx, my] }) => {
    api.start({ x: down ? mx : 0, y: down ? my : 0, immediate: down })
  })

  // Bind it to a component
  return <animated.div {...bind()} style={{ x, y }} />
}

useDrag 返回一个函数(存储在bind常量中),当调用时,该函数返回一个带有事件处理程序的对象。在这里,当在组件中添加 {...bind()} 时,实际上是在添加 onMouseDownonTouchStart 事件处理。

用法

Available gestures

提供了一些钩子函数用来处理不同的手势

HookDescription
useDrag处理拖动事件
useMove处理鼠标移动事件
useHover处理鼠标悬浮事件
useScroll处理滚动事件
useWheel处理滚轮事件
usePinch处理捏合事件
useGesture在一个Hook中处理多个手势

Usage

除了 useGesture ,其他手势API的使用方法如下:

const bind = useDrag((state) => doSomethingWith(state), config)
return <div {...bind(arg)} />
  • state 是包含手势属性的对象,包括原始的event [[@use-gesture 手势交互框架#Gesture state]]
  • config 是包含手势选项的对象 [[@use-gesture 手势交互框架#Gesture options]]
  • arg 是自定义参数,可以传递给绑定函数

Notes

  • useDrag 应该是最受欢迎的手势,但是因为pointer event的工作方式,该拖动事件可能会和触摸设备上的滚动发生冲突,所以需要明确表明这个元素是draggable的,并不触发浏览器滚动。也就是说,需要使用CSS属性:touch-action

useGesture

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

const bind = useGesture(
  {
    onDrag: (state) => doSomethingWith(state),
    onDragStart: (state) => doSomethingWith(state),
    onDragEnd: (state) => doSomethingWith(state),
    onPinch: (state) => doSomethingWith(state),
    ...
  },
  config
)

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

Gesture options

此处只记录常用选项及其概念,完整的选项设置见官方文档。 选项分为两部分:通用选项 genericOptions 、手势专用选项 gestureOptions

Generic options

OptionDescription
target添加手势的节点
eventOptionspassive/captured等自定义事件选项
window添加手势的窗口元素
enabledfalse情况下不触发

Gesture options

具体设置方法和效果见官方文档,

OptionDescription
enabled该手势是否可用
from初始位置offset
threshold当手势位移大雨阈值才触发
preventDefaultpreventDefault
axis指定轴上的运动才触发
axisThreshold阈值计算的指定轴
bounds限制手势offset的边界
scaleBounds限制规模offset的边界
angleBounds限制角度offset的边界
rubberband越界时手势的弹性系数,设置true时默认为0.15
transform将屏幕坐标映射到自定义空间坐标
filterTapstrue时,当用户刚刚单击组件,组件将不会触发拖动逻辑
preventScrolltrue时,拖动在延迟持续时间(ms)后触发并阻止窗口滚动,默认250ms
preventScrollAxis拖动指定轴

Gesture state

Gesture state attributes

const bind = useXXXX(state => {
  const {
    event,         // the source event
    xy,            // [x,y] values (pointer position or scroll offset)
    initial,       // xy value when the gesture started
    intentional,   // is the gesture intentional
    delta,         // movement delta (movement - previous movement)
    offset,        // offset since the first gesture
    lastOffset,    // offset when the last gesture started
    movement,      // displacement between offset and lastOffset
    velocity,      // momentum of the gesture per axis (in px/ms)
    distance,      // offset distance per axis      偏移距离
    direction,     // direction per axis       方向
    startTime,     // gesture start time
    elapsedTime,   // gesture elapsed time
    type,          // event type
    target,        // event target
    currentTarget, // event currentTarget
    timeStamp,     // timestamp of the event
    first,         // true when it's the first event
    last,          // true when it's the last event
    active,        // true when the gesture is active
    memo,          // value returned by your handler on its previous run
    cancel,        // function you can call to interrupt some gestures
    canceled,      // whether the gesture was canceled (drag and pinch)
    down,          // true when a mouse button or touch is down
    buttons,       // number of buttons pressed
    touches,       // number of fingers touching the screen
    args,          // arguments you passed to bind (React only)
    ctrlKey,       // true when control key is pressed
    altKey,        // "      "  alt     "      "
    shiftKey,      // "      "  shift   "      "
    metaKey,       // "      "  meta    "      "
    locked,        // whether document.pointerLockElement is set
    dragging,      // is the component currently being dragged
    moving,        // "              "              "  moved
    scrolling,     // "              "              "  scrolled
    wheeling,      // "              "              "  wheeled
    pinching       // "              "              "  pinched
  } = state
})

drag state attributes

拖动特有的属性,可以用来了解用户意图

const bind = useDrag(state => {
  const {
    swipe,         // [swipeX, swipeY] 0 if no swipe detected, -1 or 1 otherwise
    tap,           // is the drag assimilated to a tap
  } = state
})