You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React与Framer Motion中拖拽滚轮变量随机重置问题求助

问题排查与修复方案

你的拖拽滚轮出现wheelRotation随机重置为0的问题,核心原因是旋转角度未正确累积,以及状态更新方式存在缺陷,具体修复如下:

核心问题分析

  1. 旋转值被直接覆盖而非累加:当前whileDrag中直接将wheelRotation设置为单次拖拽的角度变化inc,而非在已有旋转角度基础上累加。一旦拖拽起点与当前点的角度差为0,就会将旋转值重置为0。
  2. 缺少拖拽基准记录:拖拽开始时未保存当前的wheelRotation作为基准,导致每次拖拽都是从初始状态计算角度变化,丢失之前的旋转累积值。
  3. 状态更新未用函数式方式:频繁调用setWheelRotation时,直接传值可能因React异步更新特性导致状态偏差。

修正后的代码

export const WheelContener = () => {
  const constraintsRef = useRef(null);
  const [wheelRotation, setWheelRotation] = useState(50);
  const [isDragging, setIsDragging] = useState(false);
  const xOrigin = useRef(0);
  const yOrigin = useRef(0);
  const startRotation = useRef(0);

  function DragStart(event, info) {
    xOrigin.current = info.point.x;
    yOrigin.current = info.point.y;
    startRotation.current = wheelRotation;
    setIsDragging(true);
  }

  function whileDrag(event, info) {
    if (!isDragging) return;

    const currentX = info.point.x;
    const currentY = info.point.y;
    const centerX = window.innerWidth / 2;
    const centerY = window.innerHeight / 2;

    const startAngle = Math.atan2(yOrigin.current - centerY, xOrigin.current - centerX);
    const currentAngle = Math.atan2(currentY - centerY, currentX - centerX);
    let angleDelta = ((currentAngle - startAngle) * 180) / Math.PI;

    // 处理跨象限角度突变问题
    if (angleDelta > 180) angleDelta -= 360;
    if (angleDelta < -180) angleDelta += 360;

    // 函数式更新确保基于最新状态计算
    setWheelRotation(prev => startRotation.current + angleDelta);
  }

  function DragEnd() {
    setIsDragging(false);
  }

  return (
    <>
      <motion.div className="drag-area" ref={constraintsRef}>
        <motion.div
          className="wheel"
          style={{ rotate: `${wheelRotation}deg` }}
        />
        <motion.div
          className="knob"
          drag
          dragConstraints={constraintsRef}
          onDrag={whileDrag}
          onDragStart={DragStart}
          onDragEnd={DragEnd}
        />
      </motion.div>
    </>
  );
};

关键修复点说明

  • 新增startRotation ref:拖拽开始时保存当前旋转角度,确保后续计算基于已有旋转累加,而非覆盖。
  • 函数式状态更新:使用setWheelRotation(prev => ...)保证每次更新都基于最新的状态值,避免异步更新导致的偏差。
  • 跨象限角度修正:处理角度计算时的突变问题,让旋转逻辑更符合直觉。
  • 明确旋转单位:为rotate样式添加deg单位,避免渲染引擎解析异常。
  • 补充缺失状态:添加isDragging状态定义,避免未定义变量报错。

内容的提问来源于stack exchange,提问作者Rom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:35:12