useScratch
跟踪元素上的刮擦/拖动手势,支持鼠标和触摸。
useScratch 跟踪目标元素上的鼠标和触摸拖拽手势,返回详细状态包括 isScratching、位置坐标(x、y)、增量(dx、dy)、文档级坐标(docX、docY)、元素尺寸和计时信息。它支持拖拽开始、进行中和结束事件的回调。这对于构建绘图、滑动或手势驱动的交互非常有用。
使用场景
- 构建跟踪元素内指针移动的绘图或签名板
- 实现卡片、轮播或可消除元素的滑动手势
- 创建交互式刮开或拖拽揭示效果
注意事项
- SSR 安全:在服务端渲染期间返回
isScratching: false和 undefined 坐标的默认状态。服务端不会附加事件监听器。 - 鼠标和触摸:处理
mousedown/mousemove/mouseup和touchstart/touchmove/touchend事件,实现跨设备兼容。 - 相关 hooks:参见
useMouse了解通用光标跟踪,以及useLongPress了解按住检测。
Usage
Live Editor
function Demo() { const elementRef = useRef(null); const state = useScratch(elementRef, { onScratchStart: (s) => { console.log('开始刮擦:', s); }, onScratch: (s) => { console.log('刮擦中:', s); }, onScratchEnd: (s) => { console.log('刮擦结束:', s); }, }); return ( <div style={{ padding: '20px' }}> <div ref={elementRef} style={{ width: '300px', height: '200px', border: '1px solid var(--ifm-color-emphasis-300)', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: state.isScratching ? 'var(--ifm-color-emphasis-200)' : 'var(--ifm-background-surface-color)', color: 'var(--ifm-color-content)', cursor: 'pointer', userSelect: 'none', }} > {state.isScratching ? '刮擦中...' : '点击并拖动以刮擦'} </div> <div style={{ marginTop: '20px', fontFamily: 'monospace', fontSize: '12px', color: 'var(--ifm-color-content)' }}> <div><strong>正在刮擦:</strong> {state.isScratching ? '是' : '否'}</div> {state.x !== undefined && <div><strong>x:</strong> {Math.round(state.x)}</div>} {state.y !== undefined && <div><strong>y:</strong> {Math.round(state.y)}</div>} {state.dx !== undefined && <div><strong>dx:</strong> {Math.round(state.dx)}</div>} {state.dy !== undefined && <div><strong>dy:</strong> {Math.round(state.dy)}</div>} </div> </div> ); };
Result
API
UseScratchState
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| isScratching | 是否正在刮擦 | boolean (必填) | - |
| start | 开始时间戳 | number | - |
| end | 结束时间戳 | number | - |
| x | 相对于元素的 x 坐标 | number | - |
| y | 相对于元素的 y 坐标 | number | - |
| dx | x 方向的增量 | number | - |
| dy | y 方向的增量 | number | - |
| docX | 文档中的 x 坐标 | number | - |
| docY | 文档中的 y 坐标 | number | - |
| posX | 元素在文档中的 x 位置 | number | - |
| posY | 元素在文档中的 y 位置 | number | - |
| elH | 元素高度 | number | - |
| elW | 元素宽度 | number | - |
| elX | 元素 x 位置 | number | - |
| elY | 元素 y 位置 | number | - |
UseScratchOptions
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| disabled | 是否禁用 | boolean | - |
| onScratch | 刮擦时的回调 | (state: UseScratchState) => void | - |
| onScratchStart | 开始刮擦时的回调 | (state: UseScratchState) => void | - |
| onScratchEnd | 结束刮擦时的回调 | (state: UseScratchState) => void | - |
useScratch
Returns
UseScratchState: 刮擦状态
Arguments
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| target | 目标元素 | BasicTarget<HTMLElement> (必填) | - |
| options | 配置项 | UseScratchOptions | undefined | - |
BasicTarget
export type BasicTarget<T extends TargetType = Element> = (() => TargetValue<T>) | TargetValue<T> | MutableRefObject<TargetValue<T>>;
TargetValue
type TargetValue<T> = T | undefined | null;
TargetType
type TargetType = HTMLElement | Element | Window | Document | EventTarget;