携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情。
介绍
参考: @use-gesture
- 可以将鼠标和触摸事件绑定到任何节点
- 提供了多个钩子函数
- 可以单独使用,但是建议和 [[@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()} 时,实际上是在添加 onMouseDown 和 onTouchStart 事件处理。
用法
Available gestures
提供了一些钩子函数用来处理不同的手势
| Hook | Description |
|---|---|
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
| Option | Description |
|---|---|
target | 添加手势的节点 |
eventOptions | passive/captured等自定义事件选项 |
window | 添加手势的窗口元素 |
enabled | false情况下不触发 |
Gesture options
具体设置方法和效果见官方文档,
| Option | Description |
|---|---|
enabled | 该手势是否可用 |
from | 初始位置offset |
threshold | 当手势位移大雨阈值才触发 |
preventDefault | preventDefault |
axis | 指定轴上的运动才触发 |
axisThreshold | 阈值计算的指定轴 |
bounds | 限制手势offset的边界 |
scaleBounds | 限制规模offset的边界 |
angleBounds | 限制角度offset的边界 |
rubberband | 越界时手势的弹性系数,设置true时默认为0.15 |
transform | 将屏幕坐标映射到自定义空间坐标 |
filterTaps | true时,当用户刚刚单击组件,组件将不会触发拖动逻辑 |
preventScroll | true时,拖动在延迟持续时间(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
})