実現したいこと
以下のようなReactアプリを作成したいです。
- 縦横300ピクセルの正方形の中に横長の長方形が表示される。(長方形の高さは48ピクセルで、色は黒)
- 長方形の中心と正方形の中心は一致する。(この場合、中心とは各図形の対角線の交点を意味します)
- 初期表示のとき、長方形の長いほうの辺は水平方向の向き
- 正方形のどこかをクリックすると、長方形は中心の周りに時計回りで90度回転する
- もう一度、正方形のどこかをクリックすると、長方形は中心の周りに反時計回りで90度回転して元の水平の向きに戻る。
- 以後、正方形のどこかをクリックすると上記を交互に繰り返す。
- 長方形は回転する間に以下のようなアニメーションをする。アニメーション全体の時間を1.5秒とする。
- 正方形がクリックされたと同時に長方形の色は赤に変わる。
- 赤に変わってから90度回転する。回転に要する時間をアニメ全体の時間の70%とする。
- 回転が完了してから残りの30%の時間を使って長方形の色を赤から黒に戻す。
発生している問題・分からないこと
- 以下のコマンド
npx create-react-app@latest sample-app --template typescript
で、sample-app
というアプリを作った後、sample-app/src/App.tsx
を修正していきました。
-
現状では「該当のソースコード」のものになっており、ほぼ出来ているのですが一点問題があります。
-
問題は、以下の動画のようにブラウザをリロードさせると横棒が初期表示の水平方向に置かれた状態に収まるまでにアニメーションしてしまうことです。
-
現状では上の画像のように初期表示のときにアニメーションが発生しますが、これを抑止して初めから水平方向に黒い棒が表示されるようになる修正方法を調べていますが分かっていません。
-
ご教示いただきたいのは以下の2点です。
- (1) なぜ初期表示のときにアニメーションが発生してしまうのか
- (2) どのように修正すると初期表示のときのアニメーションを抑止できるのか
よろしくお願いいたします。
該当のソースコード
Typescript
1import { PropsWithChildren, useState } from 'react' 2 3type Position = 'absolute' | 'relative' 4type Direction = 'horizontal' | 'vertical' 5 6const anotherDirection: Record<Direction, Direction> = { 7 horizontal: 'vertical', 8 vertical: 'horizontal' 9} as const 10 11const spanStyleBase = { 12 width: '100%', 13 height: '48px', 14 display: 'inline-block', 15 position: 'absolute' as Position, 16 transform: 'translate(0, -50%)', 17 top: '50%', 18 backgroundColor: 'black', 19 20 /* animation settings */ 21 animationDuration: '1.5s', 22 animationFillMode: 'forwards', 23 animationDirection: 'normal' 24} 25 26const divStyle = { 27 width: 300, 28 height: 300, 29 position: 'relative' as Position, 30 cursor: 'pointer', 31 backgroundColor: '#eee' 32} 33 34const cssKeyframes = ` 35 36 @keyframes rotate-to-vertical { 37 0% { 38 background-color: red; 39 transform: translate(0, -50%) rotate(90deg); 40 } 41 70% { background-color: red; } 42 100% { background-color: black; } 43 } 44 45 @keyframes rotate-to-horizontal { 46 0% { background-color: red; } 47 70% { 48 background-color: red; 49 transform: translate(0, -50%) rotate(90deg); 50 } 51 100% { 52 background-color: black; 53 transform: translate(0, -50%) rotate(90deg); 54 } 55 } 56` 57 58const RotatableLine = ({ direction, onClick }: { direction: Direction; onClick: () => void }) => { 59 const spanStyle = { 60 ...spanStyleBase, 61 animationName: `rotate-to-${anotherDirection[direction]}` 62 } 63 return ( 64 <div style={divStyle} onClick={onClick}> 65 <span style={spanStyle} /> 66 </div> 67 ) 68} 69 70const Container = ({ children }: PropsWithChildren) => 71 <div style={{ display: 'flex', justifyContent: 'center', marginTop: 50 }}>{children}</div> 72 73 74export default function App() { 75 const [direction, setDirection] = useState<Direction>('horizontal') 76 77 const handleToggleDirection = () => { 78 setDirection((state) => anotherDirection[state]) 79 } 80 81 return ( 82 <Container> 83 <style>{cssKeyframes}</style> 84 <RotatableLine direction={direction} onClick={handleToggleDirection} /> 85 </Container> 86 ) 87} 88
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
調べましたが分かりませんでした。
補足
特になし


回答1件
あなたの回答
tips
プレビュー