Motion
스프링 물리
stable훅의 법칙(Hooke's Law) 기반 감쇠 스프링 시뮬레이션
@hua-labs/motion-corev2.0.0
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
): SpringResultParameters
| 파라미터 | 타입 | 설명 |
|---|---|---|
currentValue | number | 현재 위치 |
currentVelocity | number | 현재 속도 |
targetValue | number | 목표 위치 (평형점) |
deltaTime | number | 시간 스텝 (초 단위) |
config | SpringConfig | 스프링 파라미터 |
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 × ΔtUsage — 단독 사용
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 파라미터 가이드
| 목적 | stiffness | damping | mass |
|---|---|---|---|
| 빠르고 탱탱 | 200 | 20 | 1 |
| 느리고 부드럽 | 50 | 15 | 2 |
| 바운시 | 200 | 10 | 1 |
| 과감쇠 (진동 없음) | 100 | 30 | 1 |
MotionProfile의 스프링 기본값
MotionProfile.spring에서 useSpringMotion 훅의 기본 파라미터를 프로필 단위로 관리한다.
interface MotionProfileSpring {
mass: number // 기본값: 프로필별 상이
stiffness: number
damping: number
restDelta: number // 정지 위치 임계값
restSpeed: number // 정지 속도 임계값
}useSpringMotion의 mass, 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이면 최단 시간에 수렴한다.