自然な動き(Natural Motion)
スプリング・慣性・イージングを使った物理ベースのアニメーションをFramer MotionとCSS Transitionで実装・比較
Framer Motion
読み込み中...
tsx
'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で書くとこうなる
jQueryの
.animate() はデフォルトで swing(ease相当)と linear のみ対応しており、スプリングのような物理ベースのアニメーションにはjQuery UIのeasingプラグインや自前のループ処理が必要でした。Reactでは Framer Motion の type: 'spring' を使うことで、stiffness(硬さ)と damping(減衰)を指定するだけで自然な物理挙動が実現できます。js
// 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();
}💡 上記のデモは、React / Next.jsです。Next.jsの基本セットアップは 公式ドキュメントを参照してください。
実装方法の比較
| 項目 | Framer Motion | CSS Transition |
|---|---|---|
| スプリング | stiffness・dampingで細かく制御可能 | 再現不可(cubic-bezierで近似のみ) |
| 慣性 | type="inertia"でドラッグ後の滑りを自動計算 | 再現不可 |
| イージング指定 | ease・cubicBezier・springを統一APIで指定 | transition-timing-functionで指定 |
| 設定コスト | 高: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の回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
同じカテゴリの他のページ
スクロール連動(Scroll Animation)
スクロール連動アニメーションのサンプル。whileInView・IntersectionObserverを使ったUIパターン実例集。Framer MotionとIntersection Observer APIで実装比較。
切り替え演出(Transition)
切り替え演出アニメーションのサンプル。フェード・スライド・スケールのUIパターン実例集。Framer MotionとCSS Transitionで実装比較。
目を引く(Attention)
目を引くアニメーションのサンプル。バウンス・シェイク・パルス・点滅のUIパターン実例集。Framer MotionとCSS Animationで実装比較。