はじめに
こんにちは!ACS 事業部の田中です。
皆さん、アプリケーションのローディング画面は好きでしょうか?
私はそんなに好きではありません。
しかし悲しいことに、待ち時間が絶対に存在しないアプリケーションは皆無でしょう。
ならば、ローディング画面は少しでも見ていて楽しいものであってほしい!
ということで、今回は React と ChakraUI を使ってアニメーションがついたローディング画面を作ってみようと思います。
こいつ、動くぞ…!
つくるもの
楽しいローディング画面の定義は人それぞれでしょうが、私はうごうご動いているものが好きです。
今回はシンプルに、画面中央でくるくると線が回るローディング画面を作ります。
UI のスタイリングには ChakraUI を使用します。
ChakraUI は公式のインストール手順に従い、pnpm add
のほかアプリのルートを ChakraUI の Provider でラップします。
chakra-ui.com
React でアニメーションやモーションを付ける際は FramerMotion ライブラリの利用などが選択肢に上がると思いますが、今回実装するものはシンプルなアニメーションなため、疑似要素で実装します。 chakra-ui.com
本記事の動作バージョンは以下です。
node: v20.4.0 typescript: 5.2.2 react: 18.2.0 chakra-ui/react: 2.8.1
完成品
上記のローディング画面は以下のように実装しています。
import { Box, Text, keyframes } from "@chakra-ui/react"; const rotate1 = keyframes` 0% {transform:translate(-50%, -50%) rotate(0)} 100% {transform:translate(-50%, -50%) rotate(360deg)} `; const rotate2 = keyframes` 0% {transform:translate(-50%, -50%) rotate(0)} 100% {transform:translate(-50%, -50%) rotate(-360deg)} `; const blurText = keyframes` 0% {filter: blur(0px);} 100% {filter: blur(4px);} `; export const CycleComponent = () => { return ( <Box h="100vh" w="100vw" bg="#222"> <Box pos="absolute" top="50%" left="50%" transform="translate(-51%, -50%)" w="240px" h="240px" borderWidth="5px" borderColor="#701B1B" borderRadius="120px" boxSizing="border-box" _after={{ content: '""', position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -100%)", w: "100px", h: "200%", bg: "#222", animation: `${rotate2} 30s infinite linear`, }} > <Box pos="absolute" top="50%" left="50%" transform="translate(-50%, -50%)" w="200px" h="200px" color="#888" textAlign="center" borderWidth="5px" borderColor="#803030" borderRadius="100px" zIndex="20" textTransform="uppercase" _before={{ content: '""', position: "absolute", top: "50%", left: "50%", transform: "translate(-53%, -50%)", w: "106%", h: "100px", bg: "#222", animation: `${rotate2} 10s infinite linear`, }} _after={{ content: '""', position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -53%)", w: "100px", h: "106%", bg: "#222", animation: `${rotate1} 15s infinite linear`, }} > <Box pos="absolute" top="50%" left="50%" transform="translate(-50%, -50%)" w="140px" h="140px" borderWidth="5px" borderColor="#A04949" borderRadius="70px" zIndex="20" display="flex" justifyContent="center" alignItems="center" _after={{ content: '""', position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -55%)", w: "40px", h: "110%", bg: "#222", animation: `${rotate1} 8s infinite linear`, }} > {["L", "o", "a", "d", "i", "n", "g"].map((letter, index) => ( <Text as="span" key={index} fontSize="sm" fontWeight="bold" mx="0.5" color="#B36D6D" zIndex="100" animation={`${blurText} 1.5s ${index / 5}s infinite alternate`} > {letter} </Text> ))} </Box> </Box> </Box> </Box> ); };
肝になるのはアニメーション定義の部分です。
このコードでは、3 つのアニメーションを定義しています。
keyframes
によりアニメーションの中間地点のスタイルを定義することによって、一連のアニメーションの中間ステップを制御することができます。
rotate1
, rotate2
rotate1
,rotate2
はそれぞれ線の回転用アニメーションを定義しています。
開始時と終了時の回転度合いを定義しており、rotate1
は時計回り、rotate2
は反時計回りに回転します。
const rotate1 = keyframes` 0% {transform:translate(-50%, -50%) rotate(0)} 100% {transform:translate(-50%, -50%) rotate(360deg)} `; const rotate2 = keyframes` 0% {transform:translate(-50%, -50%) rotate(0)} 100% {transform:translate(-50%, -50%) rotate(-360deg)} `;
blurText
blurText
は文字のぼやけアニメーションを定義しています。
開始時にはぼかしなし、終了時には 4px のぼかしをかけるようにしています。
const blurText = keyframes` 0% {filter: blur(0px);} 100% {filter: blur(4px);} `;
アニメーションの定義ができたら、あとはそれを適用する要素に animation
プロパティを指定するだけです。
このローディングアニメーションでは、複数の Box 要素に疑似要素を使用して追加の回転アニメーションを実装しています。
外側と内側の Box では _after
により半分覆う形状を作り回転させることで動きを出しています。
真ん中の Box では _before
と_after
を使用して横方向と縦方向の半分をそれぞれ覆う形状を作り、回転させることで動きを出しています。
おわりに
このように、アニメーション用のライブラリを利用せずとも単純な動きのアニメーションであれば簡単に実装できてしまいます。
なんとなくアニメーションというと複雑なコードを書かないといけないんじゃないかという先入観があったのですが、考え方はとてもシンプルですね。
動きが入るだけでぐっとアプリケーションが "それっぽく" もなりますし、ローディング画面の退屈さもまぎれることでしょう。
延々見続けてもいいくらいですね。
え?ローディング画面じゃなくて肝心のコンテンツを早く表示してほしい?
そりゃそうだ。
私達 ACS 事業部は Azure・AKS を活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。
また、一緒に働いていただける仲間も募集中です!
切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。