mcpField
M
motion

motion

github.com/lucking7デザイン・UI90 回インストール
リポジトリ

motion について

Motionは、JavaScript、React、Vueでインターフェースを開発する人向けのアニメーションライブラリです。ジェスチャー、スクロール、レイアウトのアニメーションに対応し、LazyMotionでバンドルサイズを抑えられます。

主な機能

  1. 01JavaScript、React、Vueのアニメーション
  2. 02スクロール・ビューポートアニメーション
  3. 03ドラッグとジェスチャー操作
  4. 04Variantsによるアニメーション制御
  5. 05LazyMotionによるバンドル最適化

活用シーン

  1. 01Webアプリの要素に動きを付ける
  2. 02子要素のアニメーションを順序付ける
  3. 03スクロールや表示を契機とする効果の作成
  4. 04Reactでアニメーションのバンドルサイズを抑える

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lucking7/motiondev-skills --skill motion

インストール後、Claude Code で/motionを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

reference/
examples.json
examples.md
javascript.md
react.md
vue.md
scripts/
get-example.sh
search-examples.sh

詳細

モーションアニメーションライブラリ

Motion(パッケージ:motion、以前の名称はframer-motion)は、JavaScript、React、Vue向けの業界標準アニメーションライブラリです。

インストール

npm install motion      # React/JS
npm install motion-v    # Vue

プラットフォーム別クイックリファレンス

JavaScript
import { animate, scroll, inView, stagger, hover, press } from "motion"

// Basic animation
animate("#box", { x: 100, opacity: 1 })

// With spring physics
animate(element, { scale: 1.2 }, { type: "spring", stiffness: 300, damping: 30 })

// Staggered list
animate("li", { opacity: 1 }, { delay: stagger(0.1) })

// Scroll-linked
scroll(animate("#progress", { scaleX: [0, 1] }))

// Viewport detection
inView(".card", ({ target }) => {
  animate(target, { opacity: 1, y: 0 })
})

// Gestures
hover(".btn", el => {
  animate(el, { scale: 1.1 })
  return () => animate(el, { scale: 1 })
})

press(".btn", el => {
  animate(el, { scale: 0.95 })
  return () => animate(el, { scale: 1 })
})
React
import { motion, AnimatePresence, useScroll, useTransform } from "motion/react"

// Basic motion component
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0 }}
  transition={{ type: "spring" }}
/>

// Gestures
<motion.button
  whileHover={{ scale: 1.1 }}
  whileTap={{ scale: 0.95 }}
  drag="x"
  dragConstraints={{ left: 0, right: 100 }}
/>

// Layout animations
<motion.div layout layoutId="shared-element" />

// Scroll animations
const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -300])
<motion.div style={{ y }} />
Vue
<script setup>
import { motion, AnimatePresence } from "motion-v"
</script>

<template>
  <motion.div
    :initial="{ opacity: 0 }"
    :animate="{ opacity: 1 }"
    :exit="{ opacity: 0 }"
    :whileHover="{ scale: 1.1 }"
  />
</template>

コア API

APIプラットフォーム説明
animate()すべてスプリング/トゥイーンで要素をアニメーション化
scroll()JSスクロール連動アニメーション
inView()JSビューポートの検出
hover()JSホバージェスチャー
press()JS押下/タップジェスチャー
stagger()すべて遅延をずらす
React 固有
API説明
motion.divMotion で拡張された要素
AnimatePresence終了時のアニメーション
LayoutGroupレイアウトアニメーションの調整
LazyMotionバンドルの最適化(約4.6kb)
useMotionValue()リアクティブなアニメーション値
useTransform()派生モーション値
useSpring()スプリングアニメーション値
useScroll()スクロールの進行状況
useAnimate()命令型の制御

トランジションオプション

スプリング(物理ベース)
{
  type: "spring",
  stiffness: 300,    // Higher = snappier
  damping: 30,       // Higher = less bounce
  mass: 1,           // Higher = more momentum
  bounce: 0.25,      // 0-1, alternative to stiffness/damping
  visualDuration: 0.5
}
トゥイーン(時間ベース)
{
  duration: 0.5,
  ease: "easeInOut", // or cubic bezier [0.4, 0, 0.2, 1]
  delay: 0.2,
  repeat: Infinity,
  repeatType: "reverse" // "loop" | "mirror"
}
イージング関数

"linear"、"easeIn"、"easeOut"、"easeInOut"、"circIn"、"circOut"、"backIn"、"backOut"、"anticipate"

よく使われるパターン

AnimatePresence(終了時のアニメーション)
// CRITICAL: AnimatePresence must stay mounted, children need unique keys
<AnimatePresence>
  {isVisible && (
    <motion.div
      key="modal"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    />
  )}
</AnimatePresence>
レイアウトアニメーション
<motion.div layout>
  {isExpanded ? <FullContent /> : <Summary />}
</motion.div>

// Shared element transitions
<motion.div layoutId="card-123" />
スクロールアニメーション
// Viewport-triggered
<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
/>

// Scroll-linked
const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -300])
<motion.div style={{ y }} />
ドラッグジェスチャー
<motion.div
  drag="x"
  dragConstraints={{ left: 0, right: 300 }}
  dragElastic={0.2}
  dragMomentum={true}
  dragSnapToOrigin
/>
SVG の線描画
<motion.path
  initial={{ pathLength: 0 }}
  animate={{ pathLength: 1 }}
  transition={{ duration: 2, ease: "easeInOut" }}
/>
バリアント(オーケストレーション)
const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: { staggerChildren: 0.1 }
  }
}

const item = {
  hidden: { opacity: 0, y: 20 },
  show: { opacity: 1, y: 0 }
}

<motion.ul variants={container} initial="hidden" animate="show">
  <motion.li variants={item} />
  <motion.li variants={item} />
</motion.ul>

パフォーマンス

バンドルサイズの最適化
// Full bundle: ~34 KB
import { motion } from "motion/react"

// Optimized: ~4.6 KB
import { LazyMotion, domAnimation, m } from "motion/react"

<LazyMotion features={domAnimation}>
  <m.div animate={{ x: 100 }} />
</LazyMotion>

// Minimal: 2.3 KB
import { useAnimate } from "motion/react"
Tailwind との競合を避ける
// WRONG - causes stuttering
<motion.div className="transition-all" animate={{ x: 100 }} />

// CORRECT
<motion.div animate={{ x: 100 }} />

Next.js との統合

App Router(RSC)
// components/motion-client.tsx
"use client"
import * as motion from "motion/react-client"
export { motion }

// app/page.tsx
import { motion } from "@/components/motion-client"
クライアントコンポーネントを直接使用
"use client"
import { motion } from "motion/react"

アクセシビリティ

import { MotionConfig } from "motion/react"

<MotionConfig reducedMotion="user">
  <App />
</MotionConfig>

トラブルシューティング

AnimatePresence の終了時アニメーションが機能しない

問題:終了時のアニメーションが再生されない 原因:

  1. AnimatePresence が子と一緒にアンマウントされる
  2. 一意の key prop がない
  3. 子が直接の子孫ではない

解決策:

// WRONG
{isVisible && <AnimatePresence><motion.div /></AnimatePresence>}

// CORRECT
<AnimatePresence>
  {isVisible && <motion.div key="unique" exit={{ opacity: 0 }} />}
</AnimatePresence>
スクロール可能なコンテナのレイアウト問題
<motion.div layoutScroll style={{ overflow: "auto" }}>
  <motion.div layout />
</motion.div>
固定位置のレイアウト問題
<motion.div layoutRoot style={{ position: "fixed" }}>
  <motion.div layout />
</motion.div>
レイアウトの拡大縮小による歪み
// Set borderRadius/boxShadow via style for scale correction
<motion.div layout style={{ borderRadius: 20, boxShadow: "..." }} />
大きなリストのパフォーマンス

仮想化ライブラリを使用してください:react-window、react-virtuoso、@tanstack/react-virtual

リファレンスドキュメント

プラットフォーム別の詳細なドキュメントについては、reference/ フォルダーを参照してください:

  • reference/react.md - React コンポーネントとフック
  • reference/javascript.md - Vanilla JS API
  • reference/vue.md - Vue ディレクティブとコンポーネント
  • reference/examples.md - カテゴリー別のサンプル一覧

リソース

コメント