Files
ontime/apps/client/src/features/viewers/lower-thirds/LowerLines.jsx
T
Carlos Valente de9a7a87fd V2 monorepo (#285)
* refactor(project structure): UI

* refactor(project structure): extract utilities

* refactor(project structure): remove unused

* refactor(project structure): electron

* refactor(project structure): server

refactor: migrate to vitest

refactor: monorepo config

* refactor: extract application menu

* refactor: exit process

* refactor: extract tray menu

* chore: electron build

* Added Seconds in studio clock #282
---------

Co-authored-by: Fabian Posenau <fabian@fphome.de>

---------

Co-authored-by: Fabian Posenau <fabian.p99@gmx.de>
Co-authored-by: Fabian Posenau <fabian@fphome.de>
2023-02-14 22:02:15 +01:00

187 lines
4.1 KiB
React

import { useEffect, useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
import './LowerLines.scss';
export default function LowerLines(props) {
const { lower, title, options } = props;
const defaults = {
size: 1,
transitionIn: 3,
textColour: '#fffffa',
bgColour: '#00000033',
};
const [showLower, setShowLower] = useState(true);
// Unmount if fadeOut
useEffect(() => {
if (!options.fadeOut) return;
// Calculate time
const fadeOutTime =
(parseInt(options.fadeOut, 10) +
(options.transitionIn || defaults.transitionIn)) *
1000;
if (isNaN(fadeOutTime)) return;
const timeout = setTimeout(() => {
setShowLower(false);
}, fadeOutTime);
return () => clearTimeout(timeout);
}, [options.fadeOut, options.transitionIn, defaults.transitionIn]);
useEffect(() => {
setShowLower(title.showNow);
}, [title.showNow]);
// Format messages
const showLowerMessage = lower.text !== '' && lower.visible;
// motion
// transition segments
const t = options.transitionIn || defaults.transitionIn;
const eight = t / 8;
const quarter = t / 4;
const third = t / 3;
const half = t / 2;
const lowerThirdVariants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
duration: third,
},
},
exit: {
opacity: 0,
x: -1000,
transition: {
duration: third,
},
},
};
const titleContainerVariants = {
hidden: {
left: -1000,
},
visible: {
left: 0,
transition: {
duration: third,
},
},
};
const titleVariants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
delay: quarter,
duration: half,
},
},
};
const subtitleContainerVariants = {
hidden: {
left: -1000,
},
visible: {
left: 0,
transition: {
delay: eight,
duration: third,
},
},
};
const subtitleVariants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
delay: third,
duration: third * 2,
},
},
};
const sizeMultiplier = (options.size || 1) * 4;
return (
<div
className='lower-third lines'
style={{
backgroundColor: options.keyColour || defaults.keyColour,
color: options.textColour || defaults.textColour,
fontSize: `${sizeMultiplier}vh`,
}}
>
<NavigationMenu />
<AnimatePresence>
{showLower && (
<motion.div
className='lower-container'
style={{ backgroundColor: options.bgColour || defaults.bgColour }}
variants={lowerThirdVariants}
initial='hidden'
animate='visible'
exit='exit'
>
<motion.div
className='title-container'
variants={titleContainerVariants}
>
<motion.div className='title' variants={titleVariants}>
{title.titleNow}
</motion.div>
<div className='title-decor' />
</motion.div>
<motion.div
className='subtitle-container'
variants={subtitleContainerVariants}
>
<div className='sub-decor' />
<motion.div
className='subtitle'
variants={subtitleVariants}
>
{title.presenterNow}
</motion.div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
<AnimatePresence>
{showLowerMessage && (
<motion.div
className='message-container'
key='modal'
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ scaleY: 0, opacity: 0 }}
transition={{ duration: 0.5 }}
>
<div className='message'>{lower.text}</div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}