バネのような動きを作る Spring Animation UI【JavaScript】

Spring Animationのアイキャッチ画像

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”を作るための基礎になります

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA