アニメーションを使いまわすための『motion+Slot戦略』
概要
Framer MotionをReact Slotで運用すると、アニメーションの再利用性が飛躍的に向上します。
React Slot
Slot
は子コンポーネントにpropsを渡す役割を持ちます。
これが
<Slot color="red"><AnyComponent /></Slot>
実質的にこうなります。
<AnyComponent color="red" />
Slot
本体は消えるものの、propsを介して任意のコンポーネントに機能を与えられるという点が重要です。余分なdiv
を生成することはありません。
詳しくはこちらを参照ください。
Framer Motion
Framerが提供しているアニメーションライブラリです。
どんなアニメーションでも、基本的にpropsだけで完結してしまうのが特徴です。
<motion.div
drag="x"
dragConstraints={{ left: -100, right: 100 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
/>
カスタムコンポーネントはmotion
関数に渡してアニメーションをつけます。
const MotionComponent = motion(Component);
...
<MotionComponent animate={{ scale: 0.5 }} />
motion
+Slot
で何ができる?
motion
とSlot
を組み合わせてmotion(Slot)
を作ります。すると、
motion
が提供してくれる手軽でリッチなアニメーション機能をそのまま、提供元を完全に隠蔽して提供する
ことができるようになります。
何を言っているのか、私もよくわからないので具体例に移りましょう。
具体例
motion(Slot)
を使って、みんな大好き「ふわっ」が手軽に実装できるようにしましょう。
実装
import React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { motion } from 'framer-motion';
const Container = motion(Slot);
type Custom = {
y?: number;
once?: boolean;
amount?: number;
duration?: number;
};
const defaultCustom: Custom = {
y: 20,
once: true,
amount: 0.3,
duration: 0.6,
};
const config = (custom?: Custom): React.ComponentProps<typeof Container> => {
const { y, once, amount, duration } = { ...defaultCustom, ...custom };
return {
initial: {
opacity: 0,
y,
},
whileInView: {
opacity: 1,
y: 0,
},
viewport: {
once,
amount,
},
transition: {
duration,
},
};
};
type Props = {
children: React.ReactNode;
custom?: Custom;
};
export const Enter = React.forwardRef<
React.ElementRef<typeof Container>,
Props
>(({ children, custom }, forwardedRef) => (
<Container {...config(custom)} ref={forwardedRef}>
{children}
</Container>
));
Enter.displayName = 'Enter';
使い方
たったこれだけで、h1
がふわっと入場します。
<Enter>
<h1>Hello CodeSandbox</h1>
</Enter>
CodeSandboxに使用例を上げました。
ぜひ、別窓で開いて余計なdiv
が生成されていないことをお確かめください。
注意点
motion
は内部的にrefを使用します。なので、対象のコンポーネントがカスタムコンポーネントである場合、正しくrefをフォワーディングしている必要があります。
refやforwardRef
をご存知ない方は、調べてみてください。きっと、Slot
やmotion
に比べてはるかに多くの記事がヒットするでしょう。
まとめ
motion(Slot)
で再利用性バツグンのアニメーションコンポーネントを作ることができました。
実装自体motion
の軽い延長に過ぎないので、簡単にオリジナルのアニメーションコンポーネントが作れると思います。是非お試しください。
私も色々実装してみて、またの機会に紹介したいと思います。
Discussion