UIの動きを「なんとなく滑らか」にするだけなら、
easing や lerp で十分です。
ですが、
- なんか軽い
- ちょっと機械的
- 気持ちよさが足りない
と感じることはありませんか?
その原因はシンプルで、
👉 “速度”が存在していないからです。
今回は、より自然で気持ちいい動きを作るために
Spring Animation(バネの動き)を実装します。
1.lerpとの違い
まずはいつもの lerp
x += (target - x) * 0.1これは「距離に比例して近づく」だけの動きです。
一方、Springは
velocity += (target - x) * stiffness
velocity *= damping
x += velocity速度(velocity)を持つ
これによって
- 行きすぎる(オーバーシュート)
- 揺れる(振動)
- 徐々に止まる
という、“生っぽい動き”が生まれます。
2.実装コード
<div class="stage">
<div class="ball"></div>
</div>body {
margin: 0;
background: #0f0f0f;
overflow: hidden;
}
.stage {
width: 100vw;
height: 100vh;
position: relative;
}
.ball {
width: 40px;
height: 40px;
border-radius: 50%;
background: #00ff88;
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, -50%);
}const ball = document.querySelector('.ball')
let x = window.innerWidth / 2
let y = window.innerHeight / 2
let targetX = x
let targetY = y
let vx = 0
let vy = 0
const stiffness = 0.1
const damping = 0.8
window.addEventListener('mousemove', (e) => {
targetX = e.clientX
targetY = e.clientY
})
function animate() {
const dx = targetX - x
const dy = targetY - y
vx += dx * stiffness
vy += dy * stiffness
vx *= damping
vy *= damping
x += vx
y += vy
ball.style.transform = `translate(${x}px, ${y}px)`
requestAnimationFrame(animate)
}
animate()3.実験:Spring Feel vs Lerp
このデモでは、カーソルに対してボールが追従します。
観察ポイント
- 少し遅れてついてくる
- 行き過ぎて戻る
- ピタッと止まらず、自然に減速する
👉 lerpより「生きてる感じ」が出る
4.パラメータ調整(ここが本質)
stiffness(硬さ)
- 高い → 速い / 強く引っ張る
- 低い → ゆっくり
damping(減衰)
- 高い → すぐ止まる
- 低い → ずっと揺れる
例
const stiffness = 0.2
const damping = 0.7👉 かなりビヨンビヨンする
5.よくある失敗
① dampingが低すぎる
→ 永遠に揺れる
② stiffnessが高すぎる
→ 暴れる
③ フレームレート無視
→ 環境で挙動が変わる
6.まとめ
Spring Animationは
- 速度を持つ
- オーバーシュートする
- 減衰して止まる
という特徴によって、
“気持ちいいUI”を作るための基礎になります

コメントを残す