图像与设计
用 Framer Motion 实现拖拽、点击、悬停…
在 React 中用 Framer Motion 构建拖拽、平移、点击、悬停、聚焦、触摸等交互式手势动画时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 Framer Motion 实现拖拽通用
解决思路
- 用 `drag` 属性开启拖拽,可设为 `true`、`"x"` 或 `"y"` 来限制拖拽轴,例如 `<motion.div drag="x" dragConstraints={{ left: -100, right: 100 }} whileDrag={{ scale: 1.1, cursor: "grabbing" }} />`。
- 使用拖拽相关属性:`drag`(启用拖拽轴)、`dragConstraints`(移动约束,对象或 RefObject)、`dragMomentum`(释放后是否继续惯性,默认 true)、`dragElastic`(边界弹性,默认 0)、`dragTransition`(惯性弹簧配置)、`whileDrag`(拖拽中的动画)、`onDrag`/`onDragStart`/`onDragEnd`(回调)。
- 用对象设置拖拽约束:`dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}`。
- 用 ref 设置基于容器的约束:创建一个 `constraintsRef`,把它挂到作为容器的 `motion.div` 上,再在可拖拽元素上设置 `dragConstraints={constraintsRef}`。
- 实现 pan(平移)时用 `drag="x"` 并在 `onDrag` 回调中读取指针信息,例如 `onDrag={(e, info) => { console.log(info.point); console.log(info.velocity); }}`;pan 是更底层的指针跟踪,没有惯性和约束,而 drag 带视觉反馈、惯性和约束。
- 用 `whileTap` 实现按下动画,例如 `<motion.button whileTap={{ scale: 0.95, opacity: 0.8 }} whileHover={{ scale: 1.05 }}>Click me</motion.button>`。
- 用 `whileHover` 实现悬停动画,例如 `<motion.div whileHover={{ scale: 1.1, backgroundColor: "#ff0000" }} style={{ width: 100, height: 100, backgroundColor: "#00ff00" }} />`。
- 用 `onHoverStart` 和 `onHoverEnd` 回调处理悬停开始与结束,例如 `onHoverStart={() => console.log("Hover started")}`、`onHoverEnd={() => console.log("Hover ended")}`。
- 用 `whileFocus` 实现键盘聚焦动画,例如 `<motion.input whileFocus={{ scale: 1.05, borderColor: "#00ff00" }} style={{ borderWidth: 2 }} />`。
- 用弹簧物理配置拖拽惯性:`dragTransition={{ type: "spring", stiffness: 300, damping: 20, mass: 1 }}`。
- 在容器内拖拽多个元素时,用 ref 约束容器,并对每个元素设置 `drag`、`dragConstraints={constraintsRef}`、`dragMomentum={false}`、`whileDrag={{ scale: 1.1 }}`。
- 实现滑动检测时,用 `useMotionValue(0)` 创建 x 值,用 `useTransform(x, [-100, 0, 100], [0, 1, 0])` 映射透明度,并在元素上设置 `style={{ x, opacity }}`、`drag="x"`、`dragConstraints={{ left: 0, right: 0 }}`、`dragElastic={1}`。
- 在回调中读取手势状态信息:`info.point`({ x, y } 位置)、`info.velocity`({ x, y } 速度)、`info.offset`({ x, y } 相对起点的偏移)。
- 最佳实践:用 `dragConstraints` 让元素保持在边界内;用 `dragElastic` 实现回弹效果;用 `whileDrag` 提供拖拽中的视觉反馈;用 `dragMomentum` 实现自然的惯性延续;用带 spring 的 `dragTransition` 实现基于物理的拖拽;在容器内拖拽时用 ref 作为约束。
适用边界 · 注意事项
- 如果元素需要保持在边界内,不要不使用 `dragConstraints` 就启用 `drag`。
- 不要忘记拖拽事件只有在指针移动超过阈值后才会触发。
- 不要使用过大的 `dragElastic`,否则可能导致视觉故障。
- 不要在拖拽期间同时动画相互冲突的属性(例如 scale 和 x)。