Skip to content

Commit

Permalink
Add transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
Techno11 committed Aug 15, 2024
1 parent b6ddbe9 commit 3cc3b72
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 62 deletions.
47 changes: 32 additions & 15 deletions front-end/src/apps/audience-display/displays/ad-default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { matchOccurringAtom, matchOccurringRanksAtom } from 'src/stores/recoil';
import { useEvent } from 'src/api/use-event-data';
import { Displays } from '@toa-lib/models';
import { getDisplays } from './displays';
import { FadeInOut, SlideInBottom } from 'src/components/animations';
import AbsolouteLocator from 'src/components/util/absoloute-locator';

/**
* Classic audience display that handles all scenarios.
Expand All @@ -18,19 +20,34 @@ export const AudDisplayDefault: FC<DisplayModeProps> = ({ id }) => {
const displays = getDisplays(event?.seasonKey || '');
// TODO - Have better error handling here.
if (!match || !event || !ranks || !displays) return null;
switch (id) {
case Displays.BLANK:
case Displays.MATCH_PREVIEW:
return (
<displays.matchPreview event={event} match={match} ranks={ranks} />
);
case Displays.MATCH_START:
return <displays.matchPlay event={event} match={match} ranks={ranks} />;
case Displays.MATCH_RESULTS:
return (
<displays.matchResults event={event} match={match} ranks={ranks} />
);
default:
return null;
}

return (
<>
{/* Displays.BLANK (show nothing) */}
{id === Displays.BLANK && <></>}

{/* Displays.MATCH_PREVIEW */}
<AbsolouteLocator top={0} left={0}>
<FadeInOut in={id === Displays.MATCH_PREVIEW} duration={0.5}>
<displays.matchPreview event={event} match={match} ranks={ranks} />
</FadeInOut>
</AbsolouteLocator>

{/* Displays.MATCH_START */}
<SlideInBottom
in={id === Displays.MATCH_START}
duration={0.75}
inDelay={0.25}
>
<displays.matchPlay event={event} match={match} ranks={ranks} />
</SlideInBottom>

{/* Displays.MATCH_RESULTS */}
<AbsolouteLocator top={0} left={0}>
<FadeInOut in={id === Displays.MATCH_RESULTS}>
<displays.matchResults event={event} match={match} ranks={ranks} />
</FadeInOut>
</AbsolouteLocator>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const AlliancePlay: FC<Props> = ({ alliance, participants, invert }) => {
}
: {
borderTopLeftRadius: '0.5em',
borderBottomLeftRadius: '0.em',
borderBottomLeftRadius: '0.5em',
margin: '0.5em 0 0.5em 0.5em'
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import styled from '@emotion/styled';
import { Match } from '@toa-lib/models';

const InfoContainer = styled.div`
grid-area: info;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #ffffff;
border-radius: 0.5em;
margin-left: 15%;
margin-right: 15%;
padding-top: .1em;
padding-bottom: .1em;
color: black;
line-height: 0.95;
font-size: 4vh;
font-weight: 800;
`;

const MatchTitle = ({ match }: { match: Match<any> }) => {
return (
<InfoContainer>
<div>{match.name}</div>
<div>Field {match.fieldNumber}</div>
</InfoContainer>
);
};

export default MatchTitle;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { MatchScoreBug } from './components/match-score-bug';
const Container = styled.div`
background-color: #000000;
position: absolute;
bottom: 0.5vh;
bottom: 0;
left: 32vw;
height: 18vh;
width: 36vw;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,31 @@ import { DisplayProps } from '../../displays';
import styled from '@emotion/styled';
import FGC_BG from './assets/global-bg.png';
import FGC_LOGO from './assets/fg-logo-lg.png';
import { InfoBar } from './components/info-bar';
import { AlliancePreview } from './components/alliance-preview';
import MatchTitle from './components/match-title';

const Container = styled.div`
const BGImage = styled.div`
background-image: url(${FGC_BG});
background-size: cover;
width: 100vw;
height: 100vh;
`;

const Container = styled.div`
background-size: cover;
background: linear-gradient(
to right,
#00000000,
#00000000 15%,
#0000007c 15%,
#0000007c 85%,
#00000000 85%
);
width: 100vw;
height: 100vh;
overflow: hidden;
display: grid;
grid-template-rows: 20vh 7vh 30vh 30vh;
grid-template-rows: 20vh 9vh 30vh 30vh;
grid-template-areas:
'logo'
'info'
Expand All @@ -35,35 +49,25 @@ const Logo = styled.img`
width: auto;
`;

const InfoContainer = styled.div`
grid-area: info;
display: flex;
justify-content: space-evenly;
align-items: center;
`;

export const MatchPreview: FC<DisplayProps> = ({ match, ranks }) => {
const matchParts = match.name.split(' ');
const matchNumber = matchParts[matchParts.length - 1];
return (
<Container>
<LogoContainer>
<Logo src={FGC_LOGO} />
</LogoContainer>
<InfoContainer>
<InfoBar left='match' right={matchNumber} />
<InfoBar left='field' right={match.fieldNumber} />
</InfoContainer>
<AlliancePreview
alliance='red'
participants={match.participants ?? []}
ranks={ranks}
/>
<AlliancePreview
alliance='blue'
participants={match.participants ?? []}
ranks={ranks}
/>
</Container>
<BGImage>
<Container>
<LogoContainer>
<Logo src={FGC_LOGO} />
</LogoContainer>
<MatchTitle match={match} />
<AlliancePreview
alliance='red'
participants={match.participants ?? []}
ranks={ranks}
/>
<AlliancePreview
alliance='blue'
participants={match.participants ?? []}
ranks={ranks}
/>
</Container>
</BGImage>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DisplayProps } from '../../displays';
import FGC_BG from './assets/global-bg.png';
import styled from '@emotion/styled';
import { AllianceResult } from './components/alliance-result';
import MatchTitle from './components/match-title';

const Container = styled.div`
background-image: url(${FGC_BG});
Expand Down Expand Up @@ -43,17 +44,7 @@ const ResultsText = styled.div`
`;

const InfoContainer = styled.div`
background-color: #ffffff;
border-radius: 1em;
padding: 0.5em;
text-align: center;
font-weight: bold;
font-size: 2em;
width: 24vw;
`;

const InfoText = styled.div`
line-height: 1.25em;
width: 40vw;
`;

export const MatchResults: FC<DisplayProps> = ({ match, ranks }) => {
Expand All @@ -63,8 +54,7 @@ export const MatchResults: FC<DisplayProps> = ({ match, ranks }) => {
<HeaderContainer>
<ResultsText>RESULTS</ResultsText>
<InfoContainer>
<InfoText>{match.name}</InfoText>
<InfoText>Field&nbsp;{match.fieldNumber}</InfoText>
<MatchTitle match={match} />
</InfoContainer>
</HeaderContainer>
<AllianceResult alliance='red' match={match} ranks={ranks} />
Expand Down
52 changes: 52 additions & 0 deletions front-end/src/components/animations/fade-in-out.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Box } from '@mui/material';
import React, { useEffect, useState } from 'react';

interface AnimationProps {
in: boolean;
children: React.ReactNode;
duration?: number;
inDelay?: number;
outDelay?: number;
}

const FadeInOut: React.FC<AnimationProps> = ({
in: elementIn,
children,
duration,
inDelay,
outDelay
}) => {
const [localIn, setLocalIn] = useState(false);

useEffect(() => {
let timeoutId: NodeJS.Timeout;

const delay = elementIn ? inDelay : outDelay;

if (typeof delay === 'number') {
timeoutId = setTimeout(() => {
setLocalIn(elementIn);
}, delay * 1000);
} else {
setLocalIn(elementIn);
}

return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, [elementIn, inDelay, outDelay]);
return (
<Box
sx={{
opacity: localIn ? 1 : 0,
transition: `opacity ${duration ?? 0.3}s ease-in-out`
}}
>
{children}
</Box>
);
};

export default FadeInOut;
7 changes: 7 additions & 0 deletions front-end/src/components/animations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import FadeInOut from "./fade-in-out";
import SlideInBottom from "./slide-in-bottom";

export {
FadeInOut,
SlideInBottom
}
56 changes: 56 additions & 0 deletions front-end/src/components/animations/slide-in-bottom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Box } from '@mui/material';
import React, { useEffect, useState } from 'react';

interface AnimationProps {
in: boolean;
children: React.ReactNode;
duration?: number;
inDelay?: number;
outDelay?: number;
}

const SlideInBottom: React.FC<AnimationProps> = ({
in: elementIn,
children,
duration,
inDelay,
outDelay
}) => {
const [localIn, setLocalIn] = useState(false);

useEffect(() => {
let timeoutId: NodeJS.Timeout;

const delay = elementIn ? inDelay : outDelay;

if (typeof delay === 'number') {
timeoutId = setTimeout(() => {
setLocalIn(elementIn);
}, delay * 1000);
} else {
setLocalIn(elementIn);
}

return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, [elementIn, inDelay, outDelay]);

return (
<Box
sx={{
transform: `translateY(${localIn ? '0' : '100vh'})`,
transition: `transform ${duration ?? 0.3}s ease-in-out`,
overflow: 'hidden',
height: '100vh',
width: '100vw'
}}
>
{children}
</Box>
);
};

export default SlideInBottom;
25 changes: 25 additions & 0 deletions front-end/src/components/util/absoloute-locator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

interface AbsoluteLodatorProps {
children: React.ReactNode;
top?: number;
left?: number;
right?: number;
bottom?: number;
}

const AbsoluteLodator: React.FC<AbsoluteLodatorProps> = ({
children,
top,
left,
bottom,
right
}) => {
return (
<div style={{ position: 'absolute', top, left, bottom, right }}>
{children}
</div>
);
};

export default AbsoluteLodator;
Loading

0 comments on commit 3cc3b72

Please sign in to comment.