привет! есть приложение на реакте и такая задача:
по определенному событию, из нижних левого и правого углов экрана должны вылетать дивы различной высоты и цвета, с различной скоростью и пропадать через 1-2 секунды. что-то вроде анимации "конфетти".
и вообще не представляю, как
правильно это реализовать, не просев по производительности (может вылетать до 1000 дивов за раз). возможно, 5-10т "вылетевших" анимированных дивов и не является большой нагрузкой, но все же хочется сделать все по уму.
как я себе это представляю:
0. создаем css анимацию @keyframes pull { from, to }
1. создаем кнопку, при onClick на которую запускается наш хаос
2. маунтим в dom нужное количество div-ов, у которого в инлайн стилях
width (рандом от 5 до 20px),
height (=width, чтобы были квадраты),
background (рандом из заранее составленного массива), transform rotate (рандом, чтобы квадраты летели не вертикально вверх), bottom (-width, чтобы вылетали снизу), left (рандом от 0% до 100% ширины экрана),
animation-name (pull),
animation-delay (рандом),
animation-duration (рандом) etc.
3. по завершению анимации каждого дива, удаляем его из dom.
таким образом, решением будет что-то типа такого:
... JXS page
<div className="confettiLayer">{[...Array(1000)].map((_, index) => <ConfettiItem key={item} />)}</div>
...JXS page
... компонент ConfettiItem
const [ended, setEnded] = useState(false);
const duration = useMemo(() => getRandom(1000, 2000), []); // сколько сек (от 1 до 2) див будет вылетать, перед тем как изчезнет
const size = useMemo(() => getRandom(5, 20), []); // генерируем и мемоизируем width и height квадрата
const background = useMemo(() => getRandomFromArray(BACKGROUNDS), []); // случайный фон
const rotate = useMemo(() => getRandom(-340, 20), []); // рандомное значение для transform rotate
// остальные рандомные значения
useEffect(() => {
const timer = setTimeout(() => {
setEnded(true);
}, duration);
return () => {
clearTimeout(timer);
};
}[]);
// если !ended, то рендерим див, иначе не рендерим
return ended ? null : <div style={{ background, width: size, height: size, animationName: 'pull', animationDuration: `${duration}s` ...остальные стили с рандомными значениями}} />
в целом, выглядит адекватно, но меня очень смущает реализация. чем именно смущает понять не могу, но это джуновская реализация.
подскажите, как бы вы реализовали такую задачу? не прошу реализовывать с нуля, прошу людей с опытом лишь направить джуна на нужные материалы/либы/в нужную сторону.
может есть какой-нибудь паттерн для такой задачи? может нужно реализовать через создание специального класса в стиле ООП (ООП особо не придерживаюсь, тк пока еще не познал и не понял мощь этой парадигмы).