create health component

This commit is contained in:
Viktor Rådberg
2023-09-17 18:16:58 +02:00
parent abbaec90e9
commit 444d4086aa
8 changed files with 475 additions and 259 deletions

View File

@@ -127,6 +127,10 @@ export const CommanderDamage = ({
const [timeoutFinished, setTimeoutFinished] = useState(false); const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false); const [hasPressedDown, setHasPressedDown] = useState(false);
const isSide =
player.settings.rotation === Rotation.Side ||
player.settings.rotation === Rotation.SideFlipped;
const handleCommanderDamageChange = ( const handleCommanderDamageChange = (
index: number, index: number,
increment: number, increment: number,
@@ -189,9 +193,9 @@ export const CommanderDamage = ({
}; };
const opponentIndex = opponent.index; const opponentIndex = opponent.index;
const fontSize = '6vmin'; const fontSize = isSide ? '4vmax' : '7vmin';
const fontWeight = 'bold'; const fontWeight = 'bold';
const strokeWidth = '0.5vmin'; const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
return ( return (
<CommanderDamageContainer <CommanderDamageContainer

View File

@@ -29,24 +29,6 @@ export const StyledExtraCounterButton = styled.button`
height: 100%; height: 100%;
`; `;
export const CenteredText = styled.div`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 6vmin;
font-weight: bold;
-webkit-text-stroke: 0.4vmin #ffffff;
-webkit-text-fill-color: #000000;
color: #b5b2b2;
user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
-moz-user-select: -moz-none;
-webkit-user-select: none;
-ms-user-select: none;
`;
const IconContainer = styled.div<{ const IconContainer = styled.div<{
rotation: number; rotation: number;
}>` }>`
@@ -64,6 +46,13 @@ const IconContainer = styled.div<{
}} }}
`; `;
const TextContainer = styled.div`
position: absolute;
translate: -50%;
top: 50%;
left: 50%;
`;
type ExtraCounterProps = { type ExtraCounterProps = {
Icon: ReactNode; Icon: ReactNode;
counterTotal?: number; counterTotal?: number;
@@ -83,6 +72,9 @@ const ExtraCounter = ({
const [timeoutFinished, setTimeoutFinished] = useState(false); const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false); const [hasPressedDown, setHasPressedDown] = useState(false);
const isSide =
rotation === Rotation.Side || rotation === Rotation.SideFlipped;
const handleCountChange = (increment: number) => { const handleCountChange = (increment: number) => {
if (!counterTotal) { if (!counterTotal) {
setCounterTotal(increment, type); setCounterTotal(increment, type);
@@ -115,6 +107,10 @@ const ExtraCounter = ({
setHasPressedDown(false); setHasPressedDown(false);
}; };
const fontSize = isSide ? '4vmax' : '7vmin';
const fontWeight = 'bold';
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
return ( return (
<ExtraCounterContainer> <ExtraCounterContainer>
<StyledExtraCounterButton <StyledExtraCounterButton
@@ -127,13 +123,15 @@ const ExtraCounter = ({
> >
<IconContainer rotation={rotation}> <IconContainer rotation={rotation}>
{Icon} {Icon}
<TextContainer>
<OutlinedText <OutlinedText
fontSize="6vmin" fontSize={fontSize}
fontWeight="bold" fontWeight={fontWeight}
strokeWidth="0.6vmin" strokeWidth={strokeWidth}
> >
{counterTotal ? counterTotal : undefined} {counterTotal ? counterTotal : undefined}
</OutlinedText> </OutlinedText>
</TextContainer>
</IconContainer> </IconContainer>
</StyledExtraCounterButton> </StyledExtraCounterButton>
</ExtraCounterContainer> </ExtraCounterContainer>

View File

@@ -23,10 +23,6 @@ export const StyledLifeCounterButton = styled.button`
-moz-user-select: -moz-none; -moz-user-select: -moz-none;
-webkit-user-select: none; -webkit-user-select: none;
-ms-user-select: none; -ms-user-select: none;
@media (orientation: landscape) {
max-width: 50vmin;
max-height: 50vmax;
}
`; `;
const TextContainer = styled.div<{ const TextContainer = styled.div<{
@@ -34,7 +30,6 @@ const TextContainer = styled.div<{
rotation: number; rotation: number;
}>` }>`
position: relative; position: relative;
top: -10%;
${(props) => { ${(props) => {
if ( if (
@@ -45,13 +40,11 @@ const TextContainer = styled.div<{
return css` return css`
rotate: -90deg; rotate: -90deg;
bottom: 25%; bottom: 25%;
left: -10%;
top: auto; top: auto;
`; `;
} }
return css` return css`
rotate: -90deg; rotate: -90deg;
left: -10%;
top: 25%; top: 25%;
`; `;
} }
@@ -117,7 +110,7 @@ const LifeCounterButton = ({
const fontSize = const fontSize =
rotation === Rotation.SideFlipped || rotation === Rotation.Side rotation === Rotation.SideFlipped || rotation === Rotation.Side
? '8vmax' ? '8vmax'
: '16vmin'; : '12vmin';
return ( return (
<StyledLifeCounterButton <StyledLifeCounterButton

View File

@@ -1,4 +1,5 @@
import { Player } from '../../Types/Player'; import { Player } from '../../Types/Player';
import { WakeLock } from '../../Types/WakeLock';
import LifeCounter from '../LifeCounter/LifeCounter'; import LifeCounter from '../LifeCounter/LifeCounter';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -40,6 +41,7 @@ type CountersProps = {
onPlayerChange: (updatedPlayer: Player) => void; onPlayerChange: (updatedPlayer: Player) => void;
gridAreas: string; gridAreas: string;
resetCurrentGame: () => void; resetCurrentGame: () => void;
wakeLock: WakeLock;
}; };
const Counters = ({ const Counters = ({
@@ -47,6 +49,7 @@ const Counters = ({
onPlayerChange, onPlayerChange,
gridAreas, gridAreas,
resetCurrentGame, resetCurrentGame,
wakeLock,
}: CountersProps) => { }: CountersProps) => {
return ( return (
<CountersWrapper> <CountersWrapper>
@@ -65,6 +68,7 @@ const Counters = ({
)} )}
onPlayerChange={onPlayerChange} onPlayerChange={onPlayerChange}
resetCurrentGame={resetCurrentGame} resetCurrentGame={resetCurrentGame}
wakeLock={wakeLock}
/> />
</GridItemContainer> </GridItemContainer>
); );

View File

@@ -11,15 +11,31 @@ import {
Poison, Poison,
} from '../../Icons/generated'; } from '../../Icons/generated';
const Container = styled.div<{ rotation: number }>`
width: 100%;
height: 20vmin;
display: flex;
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
height: 100%;
width: 9.3vmax;
`;
}
}}
`;
const ExtraCountersGrid = styled.div<{ rotation: number }>` const ExtraCountersGrid = styled.div<{ rotation: number }>`
display: flex; display: flex;
position: absolute; position: absolute;
width: 100%;
flex-direction: row; flex-direction: row;
flex-grow: 1; flex-grow: 1;
width: 100%;
justify-content: space-evenly;
bottom: 0; bottom: 0;
width: 100%;
pointer-events: none; pointer-events: none;
${(props) => { ${(props) => {
@@ -81,11 +97,31 @@ const ExtraCountersBar = ({
onPlayerChange(updatedPlayer); onPlayerChange(updatedPlayer);
}; };
const iconSize = '8vmin'; const iconSize =
player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side
? '5vmax'
: '10vmin';
const {
useCommanderDamage,
usePartner,
usePoison,
useEnergy,
useExperience,
} = player.settings;
const hasExtraCounters =
useCommanderDamage || usePartner || usePoison || useEnergy || useExperience;
if (!hasExtraCounters) {
return null;
}
return ( return (
<Container rotation={player.settings.rotation}>
<ExtraCountersGrid rotation={player.settings.rotation}> <ExtraCountersGrid rotation={player.settings.rotation}>
{player.settings.useCommanderDamage && ( {useCommanderDamage && (
<ExtraCounter <ExtraCounter
rotation={player.settings.rotation} rotation={player.settings.rotation}
Icon={<CommanderTax size={iconSize} opacity="0.5" color="black" />} Icon={<CommanderTax size={iconSize} opacity="0.5" color="black" />}
@@ -98,9 +134,7 @@ const ExtraCountersBar = ({
setCounterTotal={handleCounterChange} setCounterTotal={handleCounterChange}
/> />
)} )}
{Boolean( {Boolean(useCommanderDamage && usePartner) && (
player.settings.useCommanderDamage && player.settings.usePartner
) && (
<ExtraCounter <ExtraCounter
rotation={player.settings.rotation} rotation={player.settings.rotation}
Icon={<PartnerTax size={iconSize} opacity="0.5" color="black" />} Icon={<PartnerTax size={iconSize} opacity="0.5" color="black" />}
@@ -113,7 +147,7 @@ const ExtraCountersBar = ({
setCounterTotal={handleCounterChange} setCounterTotal={handleCounterChange}
/> />
)} )}
{player.settings.usePoison && ( {usePoison && (
<ExtraCounter <ExtraCounter
rotation={player.settings.rotation} rotation={player.settings.rotation}
Icon={<Poison size={iconSize} opacity="0.5" color="black" />} Icon={<Poison size={iconSize} opacity="0.5" color="black" />}
@@ -125,7 +159,7 @@ const ExtraCountersBar = ({
setCounterTotal={handleCounterChange} setCounterTotal={handleCounterChange}
/> />
)} )}
{player.settings.useEnergy && ( {useEnergy && (
<ExtraCounter <ExtraCounter
rotation={player.settings.rotation} rotation={player.settings.rotation}
Icon={<Energy size={iconSize} opacity="0.5" color="black" />} Icon={<Energy size={iconSize} opacity="0.5" color="black" />}
@@ -137,7 +171,7 @@ const ExtraCountersBar = ({
setCounterTotal={handleCounterChange} setCounterTotal={handleCounterChange}
/> />
)} )}
{player.settings.useExperience && ( {useExperience && (
<ExtraCounter <ExtraCounter
rotation={player.settings.rotation} rotation={player.settings.rotation}
Icon={<Experience size={iconSize} opacity="0.5" color="black" />} Icon={<Experience size={iconSize} opacity="0.5" color="black" />}
@@ -151,6 +185,7 @@ const ExtraCountersBar = ({
/> />
)} )}
</ExtraCountersGrid> </ExtraCountersGrid>
</Container>
); );
}; };

View File

@@ -0,0 +1,234 @@
import { useEffect, useRef, useState } from 'react';
import styled, { css, keyframes } from 'styled-components';
import { Player, Rotation } from '../../Types/Player';
import LifeCounterButton from '../Buttons/LifeCounterButton';
import { OutlinedText } from '../Misc/OutlinedText';
const LifeCountainer = styled.div<{
rotation: Rotation;
}>`
position: relative;
display: flex;
flex-direction: row;
flex-grow: 1;
width: 100%;
height: 100%;
justify-content: space-between;
align-items: center;
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
flex-direction: column-reverse;
`;
}
}}
`;
const LifeCounterTextContainer = styled.div<{
rotation: Rotation;
}>`
position: absolute;
width: 60%;
height: 100%;
margin: 0;
padding: 0;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
user-select: none;
-moz-user-select: -moz-none;
-webkit-user-select: none;
-ms-user-select: none;
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
width: 100%;
height: 60%;
`;
}
}}
`;
const TextWrapper = styled.div`
display: flex;
position: absolute;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
z-index: -1;
`;
const fadeOut = keyframes`
0% {
opacity: 1;
}
33% {
opacity: 0.6;
}
100% {
opacity: 0;
}
`;
export const RecentDifference = styled.span`
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
text-shadow: none;
background-color: rgba(255, 255, 255, 0.6);
font-variant-numeric: tabular-nums;
border-radius: 50%;
padding: 5px 10px;
font-size: 8vmin;
color: #333333;
animation: ${fadeOut} 3s 1s ease-out forwards;
`;
type HealthProps = {
player: Player;
onPlayerChange: (updatedPlayer: Player) => void;
differenceKey: number;
setDifferenceKey: (key: number) => void;
rotation: Rotation;
};
const Health = ({
player,
onPlayerChange,
differenceKey,
setDifferenceKey,
rotation,
}: HealthProps) => {
const handleLifeChange = (updatedLifeTotal: number) => {
const difference = updatedLifeTotal - player.lifeTotal;
const updatedPlayer = {
...player,
lifeTotal: updatedLifeTotal,
hasLost: false,
};
setRecentDifference(recentDifference + difference);
onPlayerChange(updatedPlayer);
setDifferenceKey(Date.now());
};
const [recentDifference, setRecentDifference] = useState(0);
const [showStartingPlayer, setShowStartingPlayer] = useState(
localStorage.getItem('playing') === 'true'
);
const [fontSize, setFontSize] = useState(16);
const textContainerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const timer = setTimeout(() => {
setRecentDifference(0);
}, 3_000);
return () => clearTimeout(timer);
}, [recentDifference]);
useEffect(() => {
if (!showStartingPlayer) {
const playingTimer = setTimeout(() => {
localStorage.setItem('playing', 'true');
setShowStartingPlayer(localStorage.getItem('playing') === 'true');
}, 3_000);
return () => clearTimeout(playingTimer);
}
}, [showStartingPlayer]);
useEffect(() => {
if (!textContainerRef.current) {
return;
}
const textContainer = textContainerRef.current;
const resizeObserver = new ResizeObserver(() => {
const calcFontSize = calculateFontSize(textContainer);
setFontSize(calcFontSize);
});
// Initially calculate font size
const initialCalculation = () => {
const calcFontSize = calculateFontSize(textContainer);
setFontSize(calcFontSize);
};
initialCalculation();
resizeObserver.observe(textContainer);
return () => {
// Cleanup: disconnect the ResizeObserver when the component unmounts.
resizeObserver.disconnect();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [textContainerRef]);
const calculateFontSize = (container: HTMLDivElement) => {
const isSide =
rotation === Rotation.SideFlipped || rotation === Rotation.Side;
const widthRatio = isSide ? container.clientHeight : container.clientWidth;
const heightRatio = isSide ? container.clientWidth : container.clientHeight;
const minRatio = Math.min(widthRatio, heightRatio);
const heightIsLarger = heightRatio > widthRatio;
const scaleFactor = heightIsLarger ? 0.8 : 1;
return minRatio * scaleFactor * 1;
};
return (
<LifeCountainer rotation={player.settings.rotation}>
<LifeCounterButton
lifeTotal={player.lifeTotal}
setLifeTotal={handleLifeChange}
rotation={player.settings.rotation}
operation="subtract"
increment={-1}
/>
<TextWrapper>
<LifeCounterTextContainer
rotation={player.settings.rotation}
ref={textContainerRef}
>
<OutlinedText
fontSize={`${fontSize}px`}
strokeWidth={`${fontSize / 16}px`}
rotation={player.settings.rotation}
>
{player.lifeTotal}
</OutlinedText>
{recentDifference !== 0 && (
<RecentDifference key={differenceKey}>
{recentDifference > 0 ? '+' : ''}
{recentDifference}
</RecentDifference>
)}
</LifeCounterTextContainer>
</TextWrapper>
<LifeCounterButton
lifeTotal={player.lifeTotal}
setLifeTotal={handleLifeChange}
rotation={player.settings.rotation}
operation="add"
increment={1}
/>
</LifeCountainer>
);
};
export default Health;

View File

@@ -2,13 +2,19 @@ import { useEffect, useState } from 'react';
import styled, { css, keyframes } from 'styled-components'; import styled, { css, keyframes } from 'styled-components';
import { theme } from '../../Data/theme'; import { theme } from '../../Data/theme';
import { Player, Rotation } from '../../Types/Player'; import { Player, Rotation } from '../../Types/Player';
import LifeCounterButton from '../Buttons/LifeCounterButton';
import { LoseGameButton } from '../Buttons/LoseButton'; import { LoseGameButton } from '../Buttons/LoseButton';
import SettingsButton from '../Buttons/SettingsButton'; import SettingsButton from '../Buttons/SettingsButton';
import CommanderDamageBar from '../Counters/CommanderDamageBar'; import CommanderDamageBar from '../Counters/CommanderDamageBar';
import ExtraCountersBar from '../Counters/ExtraCountersBar'; import ExtraCountersBar from '../Counters/ExtraCountersBar';
import { OutlinedText } from '../Misc/OutlinedText';
import PlayerMenu from '../PlayerMenu/PlayerMenu'; import PlayerMenu from '../PlayerMenu/PlayerMenu';
import Health from './Health';
import { WakeLock } from '../../Types/WakeLock';
const Lmao = styled.div`
position: absolute;
width: 100%;
height: 100%;
`;
const LifeCounterContentWrapper = styled.div<{ const LifeCounterContentWrapper = styled.div<{
backgroundColor: string; backgroundColor: string;
@@ -59,29 +65,6 @@ const LifeCounterWrapper = styled.div<{
}} }}
`; `;
const LifeCountainer = styled.div<{
rotation: Rotation;
}>`
display: flex;
flex-direction: row;
flex-grow: 1;
width: 100%;
height: 100%;
justify-content: space-between;
align-items: center;
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
flex-direction: column-reverse;
`;
}
}}
`;
const PlayerNoticeWrapper = styled.div<{ const PlayerNoticeWrapper = styled.div<{
rotation: Rotation; rotation: Rotation;
backgroundColor: string; backgroundColor: string;
@@ -128,31 +111,6 @@ const DynamicText = styled.div<{ rotation: Rotation }>`
}} }}
`; `;
const LifeCounterTextContainer = styled.p<{
rotation: Rotation;
}>`
margin: 0;
padding: 0;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
user-select: none;
-moz-user-select: -moz-none;
-webkit-user-select: none;
-ms-user-select: none;
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
rotate: 270deg;
margin-right: 25%;
`;
}
}}
`;
const fadeOut = keyframes` const fadeOut = keyframes`
0% { 0% {
opacity: 1; opacity: 1;
@@ -180,14 +138,6 @@ export const RecentDifference = styled.span`
animation: ${fadeOut} 3s 1s ease-out forwards; animation: ${fadeOut} 3s 1s ease-out forwards;
`; `;
interface LifeCounterProps {
backgroundColor: string;
player: Player;
opponents: Player[];
onPlayerChange: (updatedPlayer: Player) => void;
resetCurrentGame: () => void;
}
const hasCommanderDamageReached21 = (player: Player) => { const hasCommanderDamageReached21 = (player: Player) => {
const commanderDamageTotals = player.commanderDamage.map( const commanderDamageTotals = player.commanderDamage.map(
(commanderDamage) => commanderDamage.damageTotal (commanderDamage) => commanderDamage.damageTotal
@@ -215,12 +165,22 @@ const playerCanLose = (player: Player) => {
); );
}; };
type LifeCounterProps = {
backgroundColor: string;
player: Player;
opponents: Player[];
onPlayerChange: (updatedPlayer: Player) => void;
resetCurrentGame: () => void;
wakeLock: WakeLock;
};
const LifeCounter = ({ const LifeCounter = ({
backgroundColor, backgroundColor,
player, player,
opponents, opponents,
onPlayerChange, onPlayerChange,
resetCurrentGame, resetCurrentGame,
wakeLock,
}: LifeCounterProps) => { }: LifeCounterProps) => {
const handleLifeChange = (updatedLifeTotal: number) => { const handleLifeChange = (updatedLifeTotal: number) => {
const difference = updatedLifeTotal - player.lifeTotal; const difference = updatedLifeTotal - player.lifeTotal;
@@ -231,7 +191,7 @@ const LifeCounter = ({
}; };
setRecentDifference(recentDifference + difference); setRecentDifference(recentDifference + difference);
onPlayerChange(updatedPlayer); onPlayerChange(updatedPlayer);
setKey(Date.now()); setDifferenceKey(Date.now());
}; };
const toggleGameLost = () => { const toggleGameLost = () => {
@@ -244,7 +204,7 @@ const LifeCounter = ({
const [showStartingPlayer, setShowStartingPlayer] = useState( const [showStartingPlayer, setShowStartingPlayer] = useState(
localStorage.getItem('playing') === 'true' localStorage.getItem('playing') === 'true'
); );
const [key, setKey] = useState(Date.now()); const [differenceKey, setDifferenceKey] = useState(Date.now());
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
@@ -268,26 +228,9 @@ const LifeCounter = ({
player.settings.rotation === Rotation.SideFlipped || player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side; player.settings.rotation === Rotation.Side;
const size =
player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side
? 15
: 30;
const fontSize =
player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side
? `${size}vmax`
: `${size}vmin`;
const strokeWidth =
player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side
? `${size / 20}vmax`
: `${size / 20}vmin`;
return ( return (
<LifeCounterContentWrapper backgroundColor={backgroundColor}> <LifeCounterContentWrapper backgroundColor={backgroundColor}>
<Lmao>
<LifeCounterWrapper rotation={player.settings.rotation}> <LifeCounterWrapper rotation={player.settings.rotation}>
{player.isStartingPlayer && !showStartingPlayer && ( {player.isStartingPlayer && !showStartingPlayer && (
<PlayerNoticeWrapper <PlayerNoticeWrapper
@@ -324,36 +267,16 @@ const LifeCounter = ({
onClick={toggleGameLost} onClick={toggleGameLost}
/> />
)} )}
<LifeCountainer rotation={player.settings.rotation}> <Health
<LifeCounterButton player={player}
lifeTotal={player.lifeTotal} onPlayerChange={onPlayerChange}
setLifeTotal={handleLifeChange} differenceKey={differenceKey}
setDifferenceKey={setDifferenceKey}
rotation={player.settings.rotation} rotation={player.settings.rotation}
operation="subtract"
increment={-1}
/> />
<LifeCounterTextContainer rotation={player.settings.rotation}>
<OutlinedText fontSize={fontSize} strokeWidth={strokeWidth}>
{player.lifeTotal}
</OutlinedText>
{recentDifference !== 0 && (
<RecentDifference key={key}>
{recentDifference > 0 ? '+' : ''}
{recentDifference}
</RecentDifference>
)}
</LifeCounterTextContainer>
<LifeCounterButton
lifeTotal={player.lifeTotal}
setLifeTotal={handleLifeChange}
rotation={player.settings.rotation}
operation="add"
increment={1}
/>
</LifeCountainer>
<ExtraCountersBar player={player} onPlayerChange={onPlayerChange} /> <ExtraCountersBar player={player} onPlayerChange={onPlayerChange} />
</LifeCounterWrapper> </LifeCounterWrapper>
</Lmao>
{showPlayerMenu && ( {showPlayerMenu && (
<PlayerMenu <PlayerMenu
player={player} player={player}
@@ -361,6 +284,7 @@ const LifeCounter = ({
onPlayerChange={onPlayerChange} onPlayerChange={onPlayerChange}
setShowPlayerMenu={setShowPlayerMenu} setShowPlayerMenu={setShowPlayerMenu}
resetCurrentGame={resetCurrentGame} resetCurrentGame={resetCurrentGame}
wakeLock={wakeLock}
/> />
)} )}
</LifeCounterContentWrapper> </LifeCounterContentWrapper>

View File

@@ -1,5 +1,15 @@
import styled from 'styled-components'; import styled, { css } from 'styled-components';
import { theme } from '../../Data/theme'; import { theme } from '../../Data/theme';
import { Rotation } from '../../Types/Player';
const Container = styled.div`
display: flex;
position: relative;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
`;
const CenteredText = styled.div<{ const CenteredText = styled.div<{
strokeWidth?: string; strokeWidth?: string;
@@ -7,11 +17,9 @@ const CenteredText = styled.div<{
fillColor?: string; fillColor?: string;
fontSize?: string; fontSize?: string;
fontWeight?: string; fontWeight?: string;
rotation?: Rotation;
}>` }>`
position: absolute; position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-weight: ${(props) => props.fontWeight || ''}; font-weight: ${(props) => props.fontWeight || ''};
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
user-select: none; user-select: none;
@@ -26,6 +34,17 @@ const CenteredText = styled.div<{
-webkit-text-stroke: ${(props) => props.strokeWidth || '1vmin'} ${(props) => props.strokeColor || theme.palette.common.white}; -webkit-text-stroke: ${(props) => props.strokeWidth || '1vmin'} ${(props) => props.strokeColor || theme.palette.common.white};
-webkit-text-fill-color: ${(props) => -webkit-text-fill-color: ${(props) =>
props.fillColor || theme.palette.common.black}; props.fillColor || theme.palette.common.black};
${(props) => {
if (
props.rotation === Rotation.SideFlipped ||
props.rotation === Rotation.Side
) {
return css`
rotate: 270deg;
`;
}
}}
`; `;
const CenteredTextOutline = styled.span` const CenteredTextOutline = styled.span`
@@ -42,6 +61,7 @@ type OutlinedTextProps = {
strokeWidth?: string; strokeWidth?: string;
strokeColor?: string; strokeColor?: string;
fillColor?: string; fillColor?: string;
rotation?: Rotation;
}; };
export const OutlinedText: React.FC<OutlinedTextProps> = ({ export const OutlinedText: React.FC<OutlinedTextProps> = ({
@@ -51,17 +71,21 @@ export const OutlinedText: React.FC<OutlinedTextProps> = ({
strokeWidth, strokeWidth,
strokeColor, strokeColor,
fillColor, fillColor,
rotation,
}) => { }) => {
return ( return (
<Container>
<CenteredText <CenteredText
fontSize={fontSize} fontSize={fontSize}
fontWeight={fontWeight} fontWeight={fontWeight}
strokeWidth={strokeWidth} strokeWidth={strokeWidth}
strokeColor={strokeColor} strokeColor={strokeColor}
fillColor={fillColor} fillColor={fillColor}
rotation={rotation}
> >
{children} {children}
<CenteredTextOutline aria-hidden>{children}</CenteredTextOutline> <CenteredTextOutline aria-hidden>{children}</CenteredTextOutline>
</CenteredText> </CenteredText>
</Container>
); );
}; };