framer-motion-gestures

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Framer Motion Gestures

Framer Motion 手势动画

When to Use This Skill

何时使用此技能

Apply when implementing gesture-driven animations: drag, pan, tap, hover, focus, or touch interactions. When the user asks about drag-and-drop, interactive elements, or gesture-based UI in Framer Motion.
Related skills: For core animation use framer-motion-core; for variants use framer-motion-variants; for layout animations use framer-motion-layout.
在实现手势驱动的动画时使用:拖拽、平移、点击、悬停、聚焦或触摸交互。当用户询问Framer Motion中的拖拽、交互元素或基于手势的UI相关问题时也适用。
相关技能: 核心动画请使用 framer-motion-core;变体动画请使用 framer-motion-variants;布局动画请使用 framer-motion-layout

Drag

拖拽

Enable dragging with the
drag
prop:
jsx
<motion.div
  drag="x"
  dragConstraints={{ left: -100, right: 100 }}
  whileDrag={{ scale: 1.1, cursor: "grabbing" }}
/>
通过
drag
属性启用拖拽功能:
jsx
<motion.div
  drag="x"
  dragConstraints={{ left: -100, right: 100 }}
  whileDrag={{ scale: 1.1, cursor: "grabbing" }}
/>

Drag Props

拖拽属性

PropTypeDescription
drag
bool | "x" | "y"
Enable drag on axis
dragConstraints
object | RefObject
Movement constraints
dragMomentum
boolean
Continue momentum after release (default: true)
dragElastic
number | object
Elasticity of bounds (default: 0)
dragTransition
Transition
Spring config for momentum
whileDrag
MotionProps
Animation while dragging
onDrag
function
Callback during drag
onDragStart
function
Callback when drag starts
onDragEnd
function
Callback when drag ends
属性类型描述
drag
bool | "x" | "y"
开启指定轴向的拖拽
dragConstraints
object | RefObject
移动范围约束
dragMomentum
boolean
释放后是否保持动量(默认:true)
dragElastic
number | object
边界弹性(默认:0)
dragTransition
Transition
动量效果的弹簧配置
whileDrag
MotionProps
拖拽时的动画效果
onDrag
function
拖拽过程中的回调函数
onDragStart
function
拖拽开始时的回调函数
onDragEnd
function
拖拽结束时的回调函数

Drag Constraints

拖拽范围约束

jsx
<motion.div
  drag
  dragConstraints={{
    left: -100,
    right: 100,
    top: -50,
    bottom: 50
  }}
/>
jsx
<motion.div
  drag
  dragConstraints={{
    left: -100,
    right: 100,
    top: -50,
    bottom: 50
  }}
/>

Ref-based Constraints

基于Ref的约束

jsx
function Draggable() {
  const constraintsRef = useRef(null);

  return (
    <>
      <motion.div
        ref={constraintsRef}
        style={{
          width: 500,
          height: 500,
          backgroundColor: "#eee"
        }}
      />
      <motion.div
        drag
        dragConstraints={constraintsRef}
      />
    </>
  );
}
jsx
function Draggable() {
  const constraintsRef = useRef(null);

  return (
    <>
      <motion.div
        ref={constraintsRef}
        style={{
          width: 500,
          height: 500,
          backgroundColor: "#eee"
        }}
      />
      <motion.div
        drag
        dragConstraints={constraintsRef}
      />
    </>
  );
}

Pan

平移

Pan is similar to drag but for pointer/touch:
jsx
<motion.div
  drag="x"
  onDrag={(e, info) => {
    console.log("Position:", info.point);
    console.log("Velocity:", info.velocity);
  }}
/>
平移与拖拽类似,但针对指针/触摸操作:
jsx
<motion.div
  drag="x"
  onDrag={(e, info) => {
    console.log("Position:", info.point);
    console.log("Velocity:", info.velocity);
  }}
/>

Pan vs Drag

平移 vs 拖拽

  • Drag: Mouse/touch with visual feedback, momentum, and constraints
  • Pan: Lower-level pointer tracking without momentum
  • 拖拽:鼠标/触摸操作,带有视觉反馈、动量和范围约束
  • 平移:底层指针追踪,无动量效果

Tap (whileTap)

点击(whileTap)

Animation when pressed:
jsx
<motion.button
  whileTap={{ scale: 0.95, opacity: 0.8 }}
  whileHover={{ scale: 1.05 }}
>
  Click me
</motion.button>
按压时的动画效果:
jsx
<motion.button
  whileTap={{ scale: 0.95, opacity: 0.8 }}
  whileHover={{ scale: 1.05 }}
>
  Click me
</motion.button>

Hover (whileHover)

悬停(whileHover)

Animation on hover:
jsx
<motion.div
  whileHover={{ scale: 1.1, backgroundColor: "#ff0000" }}
  style={{ width: 100, height: 100, backgroundColor: "#00ff00" }}
/>
悬停时的动画效果:
jsx
<motion.div
  whileHover={{ scale: 1.1, backgroundColor: "#ff0000" }}
  style={{ width: 100, height: 100, backgroundColor: "#00ff00" }}
/>

onHoverStart / onHoverEnd

onHoverStart / onHoverEnd

jsx
<motion.div
  onHoverStart={() => console.log("Hover started")}
  onHoverEnd={() => console.log("Hover ended")}
/>
jsx
<motion.div
  onHoverStart={() => console.log("Hover started")}
  onHoverEnd={() => console.log("Hover ended")}
/>

Focus (whileFocus)

聚焦(whileFocus)

Animation when focused (keyboard):
jsx
<motion.input
  whileFocus={{ scale: 1.05, borderColor: "#00ff00" }}
  style={{ borderWidth: 2 }}
/>
键盘聚焦时的动画效果:
jsx
<motion.input
  whileFocus={{ scale: 1.05, borderColor: "#00ff00" }}
  style={{ borderWidth: 2 }}
/>

Drag with Spring Physics

带弹簧物理效果的拖拽

jsx
<motion.div
  drag="x"
  dragConstraints={{ left: -200, right: 200 }}
  dragTransition={{
    type: "spring",
    stiffness: 300,
    damping: 20,
    mass: 1
  }}
/>
jsx
<motion.div
  drag="x"
  dragConstraints={{ left: -200, right: 200 }}
  dragTransition={{
    type: "spring",
    stiffness: 300,
    damping: 20,
    mass: 1
  }}
/>

Drag Controls with Constraints

带约束的拖拽控制

jsx
function DraggableBox() {
  const constraintsRef = useRef(null);

  return (
    <>
      <motion.div
        ref={constraintsRef}
        style={{
          width: 500,
          height: 500,
          backgroundColor: "#f0f0f0"
        }}
      />
      {[1, 2, 3].map(i => (
        <motion.div
          key={i}
          drag
          dragConstraints={constraintsRef}
          dragMomentum={false}
          whileDrag={{ scale: 1.1 }}
        />
      ))}
    </>
  );
}
jsx
function DraggableBox() {
  const constraintsRef = useRef(null);

  return (
    <>
      <motion.div
        ref={constraintsRef}
        style={{
          width: 500,
          height: 500,
          backgroundColor: "#f0f0f0"
        }}
      />
      {[1, 2, 3].map(i => (
        <motion.div
          key={i}
          drag
          dragConstraints={constraintsRef}
          dragMomentum={false}
          whileDrag={{ scale: 1.1 }}
        />
      ))}
    </>
  );
}

Swipe Detection

滑动检测

jsx
function Swipeable() {
  const x = useMotionValue(0);
  const { scrollYProgress } = useScroll();

  const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);

  return (
    <motion.div
      style={{ x, opacity }}
      drag="x"
      dragConstraints={{ left: 0, right: 0 }}
      dragElastic={1}
    />
  );
}
jsx
function Swipeable() {
  const x = useMotionValue(0);
  const { scrollYProgress } = useScroll();

  const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);

  return (
    <motion.div
      style={{ x, opacity }}
      drag="x"
      dragConstraints={{ left: 0, right: 0 }}
      dragElastic={1}
    />
  );
}

Gesture State Info

手势状态信息

Callbacks receive
PointInfo
and
DragInfo
:
jsx
onDrag={(e, info) => {
  info.point      // { x, y } position
  info.velocity   // { x, y } velocity
  info.offset     // { x, y } offset from start
}}
回调函数会接收
PointInfo
DragInfo
jsx
onDrag={(e, info) => {
  info.point      // { x, y } 位置
  info.velocity   // { x, y } 速度
  info.offset     // { x, y } 与起始点的偏移量
}}

Best practices

最佳实践

  • ✅ Use dragConstraints to keep elements within bounds.
  • ✅ Use dragElastic for bounce-back effects.
  • ✅ Use whileDrag for visual feedback during drag.
  • ✅ Use dragMomentum for natural continuation.
  • ✅ Use dragTransition with spring for physics-based drag.
  • ✅ Use refs for constraints when dragging within a container.
  • ✅ 使用 dragConstraints 确保元素在边界内移动。
  • ✅ 使用 dragElastic 实现回弹效果。
  • ✅ 使用 whileDrag 提供拖拽时的视觉反馈。
  • ✅ 使用 dragMomentum 实现自然的拖拽延续效果。
  • ✅ 结合弹簧效果的 dragTransition 实现物理拖拽体验。
  • ✅ 在容器内拖拽时,使用Ref来设置约束范围。

Do Not

注意事项

  • ❌ Use
    drag
    without
    dragConstraints
    if the element should stay within bounds.
  • ❌ Forget that drag events only fire after the pointer moves a threshold.
  • ❌ Use excessive
    dragElastic
    — it can cause visual glitches.
  • ❌ Animate conflicting properties during drag (e.g., scale and x).
  • ❌ 如果元素需要保持在边界内,不要在使用
    drag
    时省略
    dragConstraints
  • ❌ 不要忘记拖拽事件只有在指针移动超过阈值后才会触发。
  • ❌ 不要过度使用
    dragElastic
    ——这可能导致视觉故障。
  • ❌ 拖拽期间不要动画冲突属性(例如:缩放和X轴位移)。

Learn More

了解更多