如何设计模 spring

How to design a modulo spring

我有一个应用于旋转元素的 spring:

这个东西需要左右旋转。如果我将角度附加到 spring,有时旋转的圆圈会绕很长的路。在此设置中实现模块化 spring 的正确方法是什么?

我当前的解决方案使用以下函数:

export function useNearestModulo(pp: number, m: number): number {
  const q = React.useRef<number | null>(null);

  // If the function hasn't been called yet, just return P' which satisfies
  // P' % M = P', but record it as Q for the next call.
  if (q.current == null) {
    q.current = pp;
    return pp;
  }

  // Calculate Q' that gets as close to Q as possible while satisfying
  // Q' % M = P'.
  const qq = Math.round((q.current - pp) / m) * m + pp;
  q.current = qq;
  return qq;
}

useNearestModulo returns 一个最小化绕 a 行进距离的值 圆圈。它总是满足 useNearestModulo(P, M) % M = P.

useNearestModulo(P', M) = Q' 这样 Q' % M = P' 但最小化 |Q' - Q|, 其中 Q 是上次调用的 return 值。 returned 值 Q' 是 然后用作下一次调用的 Q,依此类推。

在下面的代码中,P'是pp,Q'是qq。

示例(调用顺序):

  useNearestModulo( 0, 12) =  0
  useNearestModulo(10, 12) = -2
  useNearestModulo( 3, 12) =  3
  useNearestModulo( 7, 12) =  7
  useNearestModulo(10, 12) = 10

我使用的函数如下:

const { spring } = useSpring({
  angle: useNearestModulo(angle, 12)
});

这会使物体朝正确的方向旋转,但由于 spring 目标不断变化,因此产生的运动有点不稳定。

我仍在尝试调试抖动,但这与“spring 目标不断变化”无关。那只是我对 React 的误解。所以我发布的解决方案(基本上使用模数作为 spring 目标)是一个可行的解决方案。当然有不使用 useRef 的更简单的实现,但这正是我碰巧实现的方式。