💎
MUIでCSSアニメーションを設定する
始めに
ReactのUIライブラリの一つに Material UI がありますが、こちらを使ってアニメーションを設定する場合Transitionsに書かれているようなトランジションでアニメーションする方法しか載っておらず、CSSアニメーションの設定は見当たりませんでした。StackOverflowなどで調べたり検証コードを書いたりして設定方法が分かったので備忘録としてまとめました。
ちなみにトランジションのカスタマイズ方法は以下の記事にまとめておりますので興味があればご参照ください。
MUIでCSSアニメーションを設定する方法
MUIはemotionを使っているため、emotionを使ったkeyframesの設定をして、そこで生成された変数を使用することでCSSアニメーションが設定できます。なお、emotionのコードはMUIのパッケージに再エクスポートしているようなのでMUIパッケージからimportすることができます。
またemotionのドキュメントでは文字列で書く方法をよく見かけますが、MUIのsx設定のようにオブジェクト形式で設定することも可能です。
MUIでCSSアニメーションを設定する
import { Box, Stack } from '@mui/material';
import { keyframes, styled } from '@mui/material/styles';
// 文字列パターン
const spinAnimation = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
// オブジェクトパターン
const doubleSpinAnimation = keyframes({
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(720deg)',
},
});
const StyledRotateBox = styled('div')(() => {
return {
width: 40,
height: 40,
backgroundColor: 'red',
// styledコンポーネントにアニメーションを設定する
animation: `${spinAnimation} 1s infinite ease`,
};
});
const App = () => {
return (
<Stack spacing={2}>
<StyledRotateBox />
<Box
sx={{
width: 40,
height: 40,
backgroundColor: 'blue',
// sx propに対して設定も可能
animation: `${doubleSpinAnimation} 1s infinite ease`
}}
/>
</Stack>
)
}
一応動くけどよくない実装
他にも一応sxの中にkeyframesを定義しても動きますが、アニメーション名がグローバルで登録されるため、同じ名前を再定義すると上書きされてしまうリスクがあります。このリスクを考えるとemotionのkeyframes
で定義したものを使うのが良さそうです。
動きはするがオススメできない設定
import { Box, Stack } from '@mui/material';
const App = () => {
return (
<Stack spacing={2}>
<Box
sx={{
'@keyframes spin': {
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
},
width: 40,
height: 40,
backgroundColor: 'orange',
animation: 'spin 1s infinite ease',
}}
/>
<Box
sx={{
// sxで定義するとグローバルにアニメーションが設定され、上書きされる
'@keyframes spin': {
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(720deg)',
},
},
width: 40,
height: 40,
backgroundColor: 'purple',
animation: 'spin 1s infinite ease',
}}
/>
</Stack>
)
}
終わりに
以上がMUIでCSSアニメーションを設定する方法でした。sx propでも何となく動いていたりしてちゃんとした方法が何なのか分からず手を出しづらい状況だったのですが、本腰入れて調べてやり方が確立出来て良かったです😊
最後に検証コードを以下に貼りますので興味がある方は是非ご参照ください。
参考
Discussion