Skip to content
Docs
Motion

스프링 물리

stable

훅의 법칙(Hooke's Law) 기반 감쇠 스프링 시뮬레이션

Import

import { calculateSpring } from '@hua-labs/motion-core'
import type { SpringConfig, SpringResult } from '@hua-labs/motion-core'

calculateSpring()

감쇠 스프링 시뮬레이션의 한 스텝을 계산하는 순수 함수다. 사이드 이펙트가 없어 테스트하기 쉽다. useSpringMotion 훅이 내부적으로 매 프레임 이 함수를 호출한다.

Signature

function calculateSpring(
  currentValue: number,
  currentVelocity: number,
  targetValue: number,
  deltaTime: number,
  config: SpringConfig
): SpringResult

Parameters

파라미터타입설명
currentValuenumber현재 위치
currentVelocitynumber현재 속도
targetValuenumber목표 위치 (평형점)
deltaTimenumber시간 스텝 (초 단위)
configSpringConfig스프링 파라미터

SpringConfig

interface SpringConfig {
  stiffness: number   // 강성 (k): 높을수록 빠르게 수렴
  damping: number     // 감쇠 (c): 높을수록 진동 없이 수렴
  mass: number        // 질량 (m): 높을수록 느리게 수렴
}

SpringResult

interface SpringResult {
  value: number      // 새 위치
  velocity: number   // 새 속도
}

물리 공식

훅의 법칙과 감쇠력, 뉴턴 제2 법칙을 Semi-implicit Euler 적분으로 구현한다.

F_spring  = -k × displacement
F_damping = -c × velocity
a         = (F_spring + F_damping) / m
v_new     = v + a × Δt
x_new     = x + v_new × Δt

Usage — 단독 사용

import { calculateSpring } from '@hua-labs/motion-core'

let value = 0
let velocity = 0
const target = 100
const config = { stiffness: 100, damping: 20, mass: 1 }

function animationLoop(currentTime: number) {
  const deltaTime = 1 / 60  // 60fps

  const result = calculateSpring(value, velocity, target, deltaTime, config)
  value = result.value
  velocity = result.velocity

  // 정지 조건: 목표에 충분히 가까워지고 속도가 작으면 종료
  if (Math.abs(value - target) < 0.01 && Math.abs(velocity) < 0.01) {
    value = target
    return
  }

  requestAnimationFrame(animationLoop)
}

Usage — useSpringMotion 훅으로 사용

실제 React 컴포넌트에서는 calculateSpring을 직접 사용하지 않고 useSpringMotion 훅을 사용하는 것을 권장한다.

import { useSpringMotion } from '@hua-labs/motion-core'

function SpringCounter() {
  const { value, isAnimating } = useSpringMotion({
    from: 0,
    to: 200,
    stiffness: 150,
    damping: 25,
    mass: 1
  })

  return (
    <div>
      <span>{Math.round(value)}</span>
      {isAnimating && <span> (애니메이션 중)</span>}
    </div>
  )
}

SpringConfig 파라미터 가이드

목적stiffnessdampingmass
빠르고 탱탱200201
느리고 부드럽50152
바운시200101
과감쇠 (진동 없음)100301

MotionProfile의 스프링 기본값

MotionProfile.spring에서 useSpringMotion 훅의 기본 파라미터를 프로필 단위로 관리한다.

interface MotionProfileSpring {
  mass: number        // 기본값: 프로필별 상이
  stiffness: number
  damping: number
  restDelta: number   // 정지 위치 임계값
  restSpeed: number   // 정지 속도 임계값
}

useSpringMotionmass, stiffness, damping, restDelta, restSpeed 파라미터를 생략하면 현재 MotionProfile의 기본값이 적용된다.

Notes

  • calculateSpring은 순수 함수이므로 React, 브라우저, Node.js 어디서든 사용할 수 있다.
  • deltaTime은 초 단위다. requestAnimationFrame에서 얻은 밀리초 값을 1000으로 나눠서 전달한다.
  • 과감쇠(over-damped) 조건: damping² > 4 × stiffness × mass이면 진동 없이 수렴한다.
  • 임계 감쇠(critical damping): damping² = 4 × stiffness × mass이면 최단 시간에 수렴한다.