重さと弾み(Physics)
スプリング・慣性・イージングを使った物理ベースのアニメーションをFramer Motion / React Spring / GSAP / CSS Transitionで実装・比較
読み込み中...
'use client';
import { useState } from 'react';
import { motion, useAnimation } from 'framer-motion';
// スプリング — ボタンでバネのように弾んで移動
function SpringDemo() {
const [toggled, setToggled] = useState(false);
return (
<div>
<motion.div
animate={{ x: toggled ? 160 : 0 }}
transition={{ type: 'spring', stiffness: 200, damping: 10 }}
style={{ width: '3.5rem', height: '3.5rem', borderRadius: '0.75rem', background: '#f43f5e' }}
/>
<button onClick={() => setToggled((v) => !v)}>スプリング</button>
</div>
);
}
// 慣性 — ドラッグ後に慣性で滑るように止まる
function InertiaDemo() {
return (
<motion.div
drag="x"
dragConstraints={{ left: 0, right: 200 }}
dragTransition={{ power: 0.3, timeConstant: 200 }}
whileDrag={{ scale: 1.1 }}
style={{ width: '3.5rem', height: '3.5rem', borderRadius: '0.75rem', background: '#8b5cf6', cursor: 'grab' }}
/>
);
}
// イージング比較 — linear / easeOut / easeInOut / spring を並べて比較
const EASING_ITEMS = [
{ label: 'linear', color: '#0ea5e9', transition: { type: 'tween', duration: 1.0, ease: 'linear' } },
{ label: 'easeOut', color: '#10b981', transition: { type: 'tween', duration: 1.0, ease: 'easeOut' } },
{ label: 'easeInOut', color: '#f97316', transition: { type: 'tween', duration: 1.0, ease: 'easeInOut' } },
{ label: 'spring', color: '#f43f5e', transition: { type: 'spring', stiffness: 120, damping: 12 } },
] as const;
function EasingCompareDemo() {
const controls = useAnimation();
const [direction, setDirection] = useState<1 | -1>(1);
const run = async () => {
await controls.start((i) => ({
x: direction * 160,
transition: EASING_ITEMS[i].transition,
}));
setDirection((d) => (d === 1 ? -1 : 1));
};
return (
<div>
{EASING_ITEMS.map((item, i) => (
<motion.div
key={item.label}
custom={i}
animate={controls}
initial={{ x: 0 }}
style={{ width: '2rem', height: '2rem', background: item.color }}
/>
))}
<button onClick={run}>動かす</button>
</div>
);
}jQueryで書くとこうなる
.animate() はデフォルトで swing(ease相当)と linear のみ対応しており、スプリングのような物理ベースのアニメーションにはjQuery UIのeasingプラグインや自前のループ処理が必要でした。Reactでは Framer Motion・React Spring の物理演算や GSAP の elastic.out イージングを使うことで、重さと弾みのある物理挙動が簡単に実現できます。// easing を指定した animate()(jQuery UI が必要)
$('#box').animate({ left: '200px' }, {
duration: 600,
easing: 'easeOutBounce',
});
// swing(jQueryデフォルトのイージング)
$('#box').animate({ left: '200px' }, 600, 'swing');
// linear
$('#box').animate({ left: '200px' }, 600, 'linear');
// jQuery単体でのスプリング再現(手動ループ)
function springAnimate(el, target, stiffness, damping) {
let pos = 0, vel = 0;
function step() {
const force = (target - pos) * stiffness;
vel = (vel + force) * damping;
pos += vel;
$(el).css('transform', `translateX(${pos}px)`);
if (Math.abs(vel) > 0.1) requestAnimationFrame(step);
}
step();
}実装方法の比較
| 項目 | Framer Motion | React Spring | GSAP | CSS Transition |
|---|---|---|---|---|
| スプリング | stiffness・dampingで細かく制御可能 | tension・frictionで細かく制御可能(Framer相当) | elastic.out / back.outで近似(物理ベースではない) | 再現不可(cubic-bezierで近似のみ) |
| 慣性 | type="inertia"でドラッグ後の滑りを自動計算 | @use-gesture/reactと組み合わせて実装 | InertiaPlugin(有料Club GSAP)が必要 | 再現不可 |
| 連鎖アニメーション | stagger・delayで順番に実行 | useTrailで複数要素を自動的に遅延させて順番に動かす | staggerオプションで複数要素を自動遅延 | animation-delayで手動設定 |
| 設定コスト | 高:framer-motionのインストールが必要 | 高:@react-spring/webのインストールが必要 | 中:gsap + @gsap/reactのインストールが必要 | 低:追加ライブラリ不要 |
| 物理ベースの動き | ネイティブサポート | ネイティブサポート(バネ物理学が設計の核心) | イージング曲線での近似(真の物理演算は非対応) | 非対応(近似のみ) |
スプリングアニメーションのポイント(Framer Motion)
- •
stiffness(バネの硬さ)が高いほど素早く動き、低いほどゆっくり動く - •
damping(減衰)が低いほど長く揺れ続け、高いほどすぐ止まる - •
mass(質量)を追加するとさらに重厚感のある動きになる - • CSSの
cubic-bezierでは静止後の揺れ(オーバーシュート)の再現が困難 - • ドラッグ後の慣性には
dragTransitionのpowerとtimeConstantで挙動を調整できる
🤖 AIプロンプトテンプレート
Next.js + Framer Motion で物理ベースのアニメーションを実装してください。 - スプリングアニメーションでボタンクリック時に要素が弾んで移動する - stiffness・dampingを調整して動きの硬さ・柔らかさを表現する - linear・easeOut・springの動きをを並べて比較できるデモにする - TypeScript / Tailwind CSS v4 を使用
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
React Spring のポイント
- •
tension(バネの強さ)が高いほど素早く動き、friction(摩擦)が高いほど早く止まる - • Framer Motion の
stiffness≈tension、damping≈frictionと考えてよい - •
config.wobbly(揺れ多め)・config.gentle(滑らか)・config.stiff(キビキビ)などのプリセットが便利 - •
useTrailは複数要素を一定の遅延で順番にアニメーションさせる専用フック
🤖 AIプロンプトテンプレート
Next.js + React Spring で物理ベースのアニメーションを実装してください。 - useSpring を使ってスプリングアニメーションでボタンクリック時に要素が弾んで移動する - tension・frictionを調整して動きの硬さ・柔らかさを表現する - useTrail を使って複数要素が順番に遅延しながら表示されるアニメーションを実装 - config.gentle / config.wobbly / config.stiff を比較するデモにする - 使用ライブラリ: @react-spring/web - TypeScript / Tailwind CSS v4 を使用
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
GSAP のポイント
- • GSAP はイージング曲線ベースのため、真の物理演算(Framer・React Spring)とは仕組みが異なる
- •
elastic.out(amplitude, period)でオーバーシュートする弾む動きを表現できる(amplitude: 振れ幅、period: 振動の頻度) - •
gsap.to(elements, { stagger: 0.08 })で複数要素を一定間隔で順番にアニメーションさせる(React Spring のuseTrailに相当) - • 慣性ドラッグには有料の
InertiaPlugin(Club GSAP)が必要。無料版では@use-gesture/reactとの組み合わせが現実的
🤖 AIプロンプトテンプレート
Next.js + GSAP で重さと弾みのアニメーションを実装してください。 - useGSAP フックと contextSafe を使ってボタンクリックでアニメーションをトリガー - elastic.out(1, 0.4) でスプリング風の弾む動きを実装 - linear / power2.out / elastic.out を並べてイージング比較できるデモにする - gsap.to() の stagger オプションで複数要素を順番にアニメーションさせる - 使用ライブラリ: gsap, @gsap/react - TypeScript / Tailwind CSS v4 を使用
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
重さと弾み(Physics)は、物理法則に基づいたイージング・スプリング・バウンスを用いて、UIの動きをリアルで心地よく感じさせるアニメーション効果。
カード操作のドラッグ・ドロップ・メニューの展開収縮・スクロール連動のパララックス・フォームフィールドのフォーカスアニメーションなど、インタラクションを有機的に見せたい場面で使われる。
- •スプリング型(バネのような動き)
- •イナーシャ型(慣性あり)
- •バウンス型(跳ね返り)
- •グラビティ型(重力感)
- •フリクション型(摩擦あり)
同じカテゴリの他のページ
文字を演出する(Text Animation)| UI Memo
GSAPのSplitText・ScrambleTextで実装する文字アニメーションのサンプル。1文字ずつフェード・スライド・波・スクランブル・バラけて再集合など、テキスト演出のUIパターン実例集。
動きの質感を選ぶ(Easing)
イージングの違いを体験で比較。power・back・bounce・elasticなどGSAP・Framer Motion・CSS Transitionのeaseを一覧・比較できるUIパターン実例集。
スクロールで物語る(Scroll Storytelling)
GSAPのScrollTriggerで実装するスクロール演出のサンプル。scrub・pin・横スクロール・パララックスなど、スクロールに連動した高度なアニメーションのUIパターン実例集。デモ・コード付き。