react-spring-physics
React SpringとPopmotionを組み合わせ、スプリングダイナミクス・ジェスチャー統合・60fpsアニメーションなど、物理演算ベースのUIアニメーションを実装するためのスキルです。慣性スクロール、スプリング駆動のインタラクション、ジェスチャー操作に連動した自然な動きを構築する際に活用してください。motion-framerよりも物理的な正確さを重視したアニメーション表現が必要な場合に適しています。
description の原文を見る
Physics-based animation library combining React Spring (spring dynamics, gesture integration, 60fps animations) and Popmotion (low-level composable animation utilities, reactive streams). Use when building fluid, natural-feeling UI animations, gesture-driven interfaces, physics simulations, or spring-loaded interactions. Triggers on tasks involving React Spring hooks, spring physics, inertia scrolling, physics-based motion, animation composition, or natural UI movements. Alternative physics approach to motion-framer for more physically accurate animations.
SKILL.md 本文
React Spring Physics
React Spring の宣言的なスプリングアニメーションと Popmotion の低レベルの物理ユーティリティを組み合わせた、React アプリケーション向けの物理ベースのアニメーション。
概要
React Spring は、自然でインタラプティブなスプリング物理アニメーションを提供します。時間ベースのアニメーションとは異なり、スプリングは物理プロパティ(質量、張力、摩擦力)に基づいて動きを計算するため、有機的でリアルな動きが実現します。Popmotion はキーフレーム、減衰、慣性などのコンポーザブルなアニメーション関数でこれを補完します。
このスキルを使用するケース:
- 自然で物理ベースの UI アニメーション
- ジェスチャー駆動インターフェース(ドラッグ、スワイプ、スクロール)
- ユーザー入力に反応してモーション中断可能なアニメーション
- 速度を保ちながら状態間をスムーズに遷移する
- モメンタムスクロールと慣性効果
コアライブラリ:
@react-spring/web- スプリングアニメーション用の React フック@react-spring/three- Three.js 統合popmotion- 低レベルのアニメーションユーティリティ(オプション、高度なユースケース用)
コアコンセプト
Spring Physics
スプリングは物理シミュレーションを使用して値を現在の状態からターゲット状態にアニメーションします:
import { useSpring, animated } from '@react-spring/web'
function SpringExample() {
const springs = useSpring({
from: { opacity: 0, y: -40 },
to: { opacity: 1, y: 0 },
config: {
mass: 1, // Weight of object
tension: 170, // Spring strength
friction: 26 // Opposing force
}
})
return <animated.div style={springs}>Hello</animated.div>
}
useSpring Hook パターン
異なるユースケース向けの 2 つの初期化パターン:
// Object config (シンプル、プロップ変更時に自動更新)
const springs = useSpring({
from: { x: 0 },
to: { x: 100 }
})
// Function config (より詳細な制御、命令的な更新用 API を返す)
const [springs, api] = useSpring(() => ({
from: { x: 0 }
}), [])
// API 経由でアニメーションをトリガー
const handleClick = () => {
api.start({
from: { x: 0 },
to: { x: 100 }
})
}
Spring 設定プリセット
React Spring は組み込み設定プリセットを提供します:
import { config } from '@react-spring/web'
// 利用可能なプリセット
config.default // { tension: 170, friction: 26 }
config.gentle // { tension: 120, friction: 14 }
config.wobbly // { tension: 180, friction: 12 }
config.stiff // { tension: 210, friction: 20 }
config.slow // { tension: 280, friction: 60 }
config.molasses // { tension: 280, friction: 120 }
// 使用方法
const springs = useSpring({
from: { x: 0 },
to: { x: 100 },
config: config.wobbly
})
よくあるパターン
1. クリックトリガー型スプリングアニメーション
import { useSpring, animated } from '@react-spring/web'
function ClickAnimated() {
const [springs, api] = useSpring(() => ({
from: { scale: 1 }
}), [])
const handleClick = () => {
api.start({
from: { scale: 1 },
to: { scale: 1.2 },
config: { tension: 300, friction: 10 }
})
}
return (
<animated.button
onClick={handleClick}
style={{
transform: springs.scale.to(s => `scale(${s})`)
}}
>
Click Me
</animated.button>
)
}
2. 複数要素のトレイルアニメーション
import { useTrail, animated } from '@react-spring/web'
function Trail({ items }) {
const trails = useTrail(items.length, {
from: { opacity: 0, x: -20 },
to: { opacity: 1, x: 0 },
config: config.gentle
})
return (
<div>
{trails.map((style, i) => (
<animated.div key={i} style={style}>
{items[i]}
</animated.div>
))}
</div>
)
}
3. リスト遷移(進入・終了)
import { useTransition, animated } from '@react-spring/web'
function List({ items }) {
const transitions = useTransition(items, {
from: { opacity: 0, height: 0 },
enter: { opacity: 1, height: 80 },
leave: { opacity: 0, height: 0 },
config: config.stiff,
keys: item => item.id
})
return transitions((style, item) => (
<animated.div style={style}>
{item.text}
</animated.div>
))
}
4. スクロールベースのスプリングアニメーション
import { useScroll, animated } from '@react-spring/web'
function ScrollReveal() {
const { scrollYProgress } = useScroll()
return (
<animated.div
style={{
opacity: scrollYProgress.to([0, 0.5], [0, 1]),
scale: scrollYProgress.to([0, 0.5], [0.8, 1])
}}
>
Scroll to reveal
</animated.div>
)
}
5. ビューポート交差アニメーション
import { useInView, animated } from '@react-spring/web'
function FadeInOnView() {
const [ref, springs] = useInView(
() => ({
from: { opacity: 0, y: 100 },
to: { opacity: 1, y: 0 }
}),
{ rootMargin: '-40% 0%' }
)
return <animated.div ref={ref} style={springs}>Content</animated.div>
}
6. チェーン型非同期アニメーション
import { useSpring, animated } from '@react-spring/web'
function ChainedAnimation() {
const springs = useSpring({
from: { x: 0, background: '#ff6d6d' },
to: [
{ x: 80, background: '#fff59a' },
{ x: 0, background: '#88DFAB' },
{ x: 80, background: '#569AFF' }
],
config: { tension: 200, friction: 20 },
loop: true
})
return <animated.div style={springs} />
}
7. 速度保持機能付きスプリング
import { useSpring, animated } from '@react-spring/web'
function VelocityPreservation() {
const [springs, api] = useSpring(() => ({
x: 0,
config: { tension: 300, friction: 30 }
}), [])
const handleDragEnd = () => {
api.start({
x: 0,
velocity: springs.x.getVelocity(), // モメンタムを保持
config: { tension: 200, friction: 20 }
})
}
return <animated.div style={springs} onMouseUp={handleDragEnd} />
}
統合パターン
React Three Fiber との統合(3D)
import { useSpring, animated } from '@react-spring/three'
import { Canvas } from '@react-three/fiber'
const AnimatedBox = animated(MeshDistortMaterial)
function ThreeScene() {
const [clicked, setClicked] = useState(false)
const springs = useSpring({
scale: clicked ? 1.5 : 1,
color: clicked ? '#569AFF' : '#ff6d6d',
config: { tension: 200, friction: 20 }
})
return (
<Canvas>
<mesh onClick={() => setClicked(!clicked)} scale={springs.scale}>
<sphereGeometry args={[1, 64, 32]} />
<AnimatedBox color={springs.color} />
</mesh>
</Canvas>
)
}
Popmotion との統合(低レベル物理)
import { spring, inertia } from 'popmotion'
import { useState } from 'react'
function PopmotionIntegration() {
const [x, setX] = useState(0)
const handleDragEnd = (velocity) => {
inertia({
from: x,
velocity: velocity,
power: 0.3,
timeConstant: 400,
modifyTarget: v => Math.round(v / 100) * 100 // グリッドにスナップ
}).start(setX)
}
return <div style={{ transform: `translateX(${x}px)` }} />
}
フォームとバリデーションとの統合
import { useSpring, animated } from '@react-spring/web'
function ValidatedInput() {
const [error, setError] = useState(false)
const shakeAnimation = useSpring({
x: error ? [0, -10, 10, -10, 10, 0] : 0,
config: { tension: 300, friction: 10 },
onRest: () => setError(false)
})
return <animated.input style={shakeAnimation} />
}
パフォーマンス最適化
オンデマンドレンダリング
// アニメーションがアクティブな場合のみ再レンダリング
const [springs, api] = useSpring(() => ({
from: { x: 0 },
config: { precision: 0.01 } // 値が大きいほど更新が少ない
}), [])
複数スプリングのバッチ処理
// 複数の類似したアニメーションに useSprings を使用
const springs = useSprings(
items.length,
items.map(item => ({
from: { opacity: 0 },
to: { opacity: 1 }
}))
)
アニメーションスキップ(テスト・アクセシビリティ)
import { Globals } from '@react-spring/web'
// すべてのアニメーションをスキップ(prefers-reduced-motion)
useEffect(() => {
Globals.assign({ skipAnimation: true })
return () => Globals.assign({ skipAnimation: false })
}, [])
よくある落とし穴
1. 依存配列を忘れる
// ❌ 間違い: 依存配列がないと、レンダリングのたびに新しいスプリングが作成される
const springs = useSpring(() => ({ x: 0 }))
// ✅ 正しい: 空配列で再作成を防止
const [springs, api] = useSpring(() => ({ x: 0 }), [])
2. スプリング値の変更
// ❌ 間違い: 直接変更
springs.x.set(100)
// ✅ 正しい: API を使用してアニメーション化
api.start({ x: 100 })
3. 設定精度を無視する
// ❌ デフォルト精度が細かすぎる(0.0001)、不要なレンダリングが発生
const springs = useSpring({ x: 0 })
// ✅ ユースケースに適切な精度を設定
const springs = useSpring({
x: 0,
config: { precision: 0.01 } // ターゲットの 0.01 以内で更新を停止
})
4. 速度を処理しない
// ❌ アニメーション割り込み時に突然停止
api.start({ x: 0 })
// ✅ モメンタムを保持
api.start({
x: 0,
velocity: springs.x.getVelocity()
})
5. 設定パターンを混ぜる
// ❌ 間違い: オブジェクト設定と関数設定の両方を使用
const springs = useSpring({
from: { x: 0 }
})
api.start({ x: 100 }) // api は未定義
// ✅ 正しい: 命令的制御に関数設定を使用
const [springs, api] = useSpring(() => ({
from: { x: 0 }
}), [])
6. 数値以外の値をアニメーション化する
// ❌ 間違い: スプリングは複雑な文字列を直接補間できない
const springs = useSpring({ transform: 'translateX(100px) rotate(45deg)' })
// ✅ 正しい: 個別の値をアニメーション化
const springs = useSpring({ x: 100, rotation: 45 })
// その後組み合わせ: transform: `translateX(${x}px) rotate(${rotation}deg)`
リソース
スクリプト
spring_generator.py- React Spring ボイラープレートコード生成physics_calculator.py- 最適なスプリング物理パラメータの計算
リファレンス
react_spring_api.md- React Spring フックと API の完全リファレンスpopmotion_api.md- Popmotion 関数とリアクティブストリームphysics_guide.md- スプリング物理の詳細解説とチューニングガイド
アセット
starter_spring/- React Spring サンプル付き React + Vite テンプレートexamples/- 実例パターン(ジェスチャー、スクロール、3D 統合)
関連スキル
- motion-framer - バリアント型の別の宣言的アニメーションアプローチ
- gsap-scrolltrigger - 複雑なシーケンス向けのタイムラインベースのアニメーション
- react-three-fiber - 3D シーン管理(アニメーション用は @react-spring/three を使用)
- animated-component-libraries - Motion を使用した事前構築のアニメーション化コンポーネント
物理 vs タイムライン: ユーザー入力に反応する自然で物理ベースの動きには React Spring を使用します。正確なタイムラインベースのコレオグラフィと複雑なマルチステップシーケンスには GSAP を使用します。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- freshtechbro
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/freshtechbro/claudedesignskills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。