6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React + TypeScript: Framer Motionでアニメーションを加える

Posted at

Framer Motionは、本番環境に対応したReact用のモーションライブラリです。構文は宣言的で、複雑なアニメーションのコードも簡潔に書けます。つまり、コードベースが読みやすく、保守しやすいということです。

Framer Motionは、つぎのようにインストールしてください。

npm install framer-motion

アニメーションの基本

宣言的な構文でアニメーションのコードを書くために、中心的な役割を果たすのがmotionコンポーネントです。DOM要素として扱え、アニメーションの機能が拡張されます。

たとえば、アニメーションさせたい要素が<div />であれば、motionコンポーネントをimportしたうえで、つぎのように<motion.div />に差し替えてください。

src/App.tsx
import { motion } from 'framer-motion';

export default function App() {
	return (
		// <div />
		<motion.div />
	);
}

motionコンポーネントにアニメーションを加えるのはanimateプロパティです。値をオブジェクトでつぎのように定めれば、コンポーネントが表示されると、サイズ(scale)は半分になりつつ、透明(opacity)に変化します。

src/App.tsx
import { motion } from 'framer-motion';

export default function App() {
	return (
		<motion.div
			animate={{ opacity: 0, scale: 0.5 }}
		/>
	);
}

アニメーションが速すぎるかもしれません。どう変化させるかを調整するのは、transitionプロパティです(「Transition」参照)。durationでアニメーションにかける秒数を定めましょう。

src/App.tsx
export default function App() {
	return (
		<motion.div
			animate={{ opacity: 0, scale: 0.5 }}
			transition={{ duration: 1 }}
		/>
	);
}

initialプロパティを用いれば、アニメーションの初期値が決められます。DOM(<motion.div />)のもともとの設定と異なる初期値から、本来の表示に戻るよう変化させる例がつぎのコードです(サンプル001)。透明な(opacity)要素が左(x)から姿を表し、拡大(scale)しながら、もともとの設定に落ち着きます。

src/App.tsx
export default function App() {
	return (
		<motion.div
			initial={{ opacity: 0, scale: 0, x: -400 }}
			// animate={{ opacity: 0, scale: 0.5 }}
			animate={{ opacity: 1, scale: 1, x: 0 }}
			transition={{ duration: 1 }}
		/>
	);
}

サンプル001■React + TypeScript: Framer Motion Examples 01
https://codesandbox.io/s/react-typescript-framer-motion-examples-01-gfy2zq

キーフレーム

animateに与えるオブジェクトプロパティの値を配列で渡して、段階的に変化させるのがキーフレームです。以下のコード例は、つぎの3つのプロパティを開始値から終了値に変化させます。

プロパティ 開始値 終了値
scale 2 1
rotate 180 0
borderRadius 50% 0%
src/App.tsx
export default function App() {
	return (
		<motion.div
			animate={{
				scale: [2, 1],
				rotate: [180, 0],
				borderRadius: ['50%', '0%']
			}}
			transition={{
				duration: 2
			}}
		/>
	);
}

プロパティ値(キーフレーム)は、配列要素にいくつ加えても構いません。そうすると、細かなアニメーションが定められるでしょう。

src/App.tsx
export default function App() {
	return (
		<motion.div
			animate={{
				// scale: [2, 1],
				scale: [1, 2, 2, 1, 1],
				// rotate: [180, 0],
				rotate: [0, 0, 180, 180, 0],
				// borderRadius: ['50%', '0%']
				borderRadius: ['0%', '0%', '50%', '50%', '0%']
			}}

		/>
	);
}

デフォルトでは、キーフレーム間のアニメーション時間は均等です。transitiontimesで、この間隔が調整できます(サンプル002)。値は0が開始、1で終了する小数値です。さらに、easeはイージング関数、repeatが繰り返し回数、repeatDelayでつぎの繰り返しまでの溜め(待ち秒数)を定められます。

src/App.tsx
export default function App() {
	return (
		<motion.div

			transition={{
				duration: 2,
				ease: 'easeInOut',
				times: [0, 0.2, 0.5, 0.8, 1],
				repeat: Infinity,
				repeatDelay: 1
			}}
		/>
	);
}

サンプル002■React + TypeScript: Framer Motion Examples 02
https://codesandbox.io/s/react-typescript-framer-motion-examples-02-8k925n

ジェスチャーアニメーション

ジェスチャーは、アクティブになるとその間コンポーネントの視覚的な状態にアニメーションを加えるつぎのようなヘルパープロパティです。

つぎのコード例では、whileHoverwhileTapを用いました。値のアニメーションの定め方は、animateと同じです。以下のサンプル003で、コードと動きを見比べていただくのが手っ取り早いでしょう。

src/App.tsx
export default function App() {
	return (
		<div>
			<motion.div whileHover={{ scale: 1.2 }} whileTap={{ scale: 0.8 }} />
		</div>
	);
}

サンプル003■React + TypeScript: Framer Motion Examples 03
https://codesandbox.io/s/react-typescript-framer-motion-examples-03-dfgpq4

ドラッグ

ドラッグのジェスチャーアニメーションは、dragプロパティを加えるだけです。ドラッグ領域の上(top)下(bottom)左(left)右(right)の範囲は、dragConstraintsプロパティで決められます。

src/Example.tsx
export const Example: FC = () => {
	return (
		<>
			<motion.div
				drag
				dragConstraints={{
					top: -50,
					left: -50,
					right: 50,
					bottom: 50
				}}
			/>
		</>
	);
};

ドラッグ領域を数値でなく、DOM要素の矩形で定めたい場合もあるでしょう。そのときは、範囲にしたいDOM要素にrefを与えてください。dragConstraintsプロパティの値とするのはそのrefオブジェクトです(サンプル004)。

src/Example.tsx
export const Example: FC = () => {
	const constraintsRef = useRef<HTMLDivElement>(null);
	return (
		<>
			<motion.div ref={constraintsRef} />
			{/* <motion.div
				drag
				dragConstraints={{
					top: -50,
					left: -50,
					right: 50,
					bottom: 50
				}}
			/> */}
			<motion.div drag dragConstraints={constraintsRef} />
		</>
	);
};

サンプル004■React + TypeScript: Framer Motion Examples 04
https://codesandbox.io/s/react-typescript-framer-motion-examples-04-3rnffz

Framer Motionの基本的な使い方について、作例のコードを書き進めながらご説明しました。作例は公式サイトの「Examples」から拾いつつ、細かな手を加えています。

「Examples」には、本稿で説明しきれなかったサンプルがまだ多くあるので、興味のある方はご覧になるとよいでしょう。もっとも、コードの説明はほぼなく、サンプルにも不要なモジュールやコードが残っていたりするのでご注意ください。

この記事が好評でしたら、続編も考えます。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?