signal-desktop/ts/components/AnimatedEmojiGalore.tsx
2022-11-17 16:45:19 -08:00

72 lines
1.6 KiB
TypeScript

// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { animated, to as interpolate, useSprings } from '@react-spring/web';
import { random } from 'lodash';
import { Emojify } from './conversation/Emojify';
export type PropsType = {
emoji: string;
onAnimationEnd: () => unknown;
rotate?: number;
scale?: number;
x?: number;
};
const NUM_EMOJIS = 16;
const MAX_HEIGHT = 1280;
const to = (i: number, f: () => unknown) => ({
delay: i * random(80, 120),
rotate: random(-24, 24),
scale: random(0.5, 1.0, true),
y: -144,
onRest: i === NUM_EMOJIS - 1 ? f : undefined,
});
const from = (_i: number) => ({
rotate: 0,
scale: 1,
y: MAX_HEIGHT,
});
function transform(y: number, scale: number, rotate: number): string {
return `translateY(${y}px) scale(${scale}) rotate(${rotate}deg)`;
}
export function AnimatedEmojiGalore({
emoji,
onAnimationEnd,
}: PropsType): JSX.Element {
const [springs] = useSprings(NUM_EMOJIS, i => ({
...to(i, onAnimationEnd),
from: from(i),
config: {
mass: 20,
tension: 120,
friction: 80,
clamp: true,
},
}));
return (
<>
{springs.map((styles, index) => (
<animated.div
// eslint-disable-next-line react/no-array-index-key
key={index}
style={{
left: `${random(0, 100)}%`,
position: 'absolute',
transform: interpolate(
[styles.y, styles.scale, styles.rotate],
transform
),
}}
>
<Emojify sizeClass="extra-large" text={emoji} />
</animated.div>
))}
</>
);
}