fix: adapt to vertical resolution and fix flickering
This commit is contained in:
@@ -1,51 +1,61 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
import React, { useMemo } from 'react';
|
||||
import { Img, spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
|
||||
interface AlbumsSceneProps {
|
||||
interface AlbumSceneProps {
|
||||
message: string;
|
||||
emoji: string;
|
||||
data: {
|
||||
photos: number;
|
||||
albums: {
|
||||
name: string;
|
||||
cover: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
export default function AlbumsScene({ message, emoji, data }: AlbumsSceneProps) {
|
||||
const albums = useMemo(() => data.albums.map((album, index) => ({
|
||||
name: album.name,
|
||||
cover: album.cover,
|
||||
})), [data.albums]);
|
||||
|
||||
|
||||
export default function AlbumScene({ message, emoji, data }: AlbumSceneProps) {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
const initialDelay = useRef(frame);
|
||||
|
||||
const albums = useMemo(() => data.albums, [data.albums]);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
animation: "zoomIn 1s ease forwards",
|
||||
height: "100%",
|
||||
padding: "20px",
|
||||
gap: 40
|
||||
}}>
|
||||
<p style={{
|
||||
fontSize: 70,
|
||||
padding: "0 70px",
|
||||
color: "lightblue",
|
||||
marginTop: 40,
|
||||
textAlign: "center",
|
||||
transition: "opacity 1s ease",
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: 20
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
<span style={{ fontSize: 80 }}>{emoji}</span>
|
||||
<h1 style={{
|
||||
fontSize: 50,
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
margin: 0,
|
||||
maxWidth: "80%"
|
||||
}}>
|
||||
{message}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(4, 1fr)",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gap: 20,
|
||||
width: "100%",
|
||||
maxWidth: 600
|
||||
}}>
|
||||
{albums.map((album, index) => {
|
||||
const delay = (initialDelay.current) + (index * 0.1 * fps);
|
||||
const delay = index * 5;
|
||||
const scale = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
@@ -57,56 +67,37 @@ export default function AlbumsScene({ message, emoji, data }: AlbumsSceneProps)
|
||||
});
|
||||
|
||||
return (
|
||||
<div key={index} style={{
|
||||
border: "1px solid lightblue",
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}>
|
||||
<img
|
||||
key={index}
|
||||
src={album.cover}
|
||||
alt="memory"
|
||||
style={{
|
||||
width: 200,
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
borderRadius: 10,
|
||||
margin: 10,
|
||||
<div
|
||||
key={album.name}
|
||||
style={{
|
||||
transform: `scale(${scale})`,
|
||||
}}
|
||||
/>
|
||||
<p style={{
|
||||
fontSize: 20,
|
||||
textAlign: "center",
|
||||
marginTop: 10,
|
||||
color: "lightblue",
|
||||
}}>
|
||||
{album.name}
|
||||
</p>
|
||||
opacity: scale,
|
||||
}}
|
||||
>
|
||||
<Img
|
||||
src={album.cover}
|
||||
alt={album.name}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
borderRadius: 15,
|
||||
boxShadow: "0 4px 8px rgba(0,0,0,0.2)",
|
||||
}}
|
||||
/>
|
||||
<p style={{
|
||||
color: "white",
|
||||
fontSize: 18,
|
||||
textAlign: "center",
|
||||
margin: "10px 0",
|
||||
fontWeight: "bold"
|
||||
}}>
|
||||
{album.name}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add this CSS to your global styles or a CSS-in-JS solution
|
||||
const styles = `
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Inject styles into the document
|
||||
const styleSheet = document.createElement("style");
|
||||
styleSheet.type = "text/css";
|
||||
styleSheet.innerText = styles;
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
@@ -1,55 +1,59 @@
|
||||
import React from 'react'
|
||||
import { spring, useCurrentFrame, useVideoConfig, interpolate } from 'remotion';
|
||||
import React, { useMemo } from 'react';
|
||||
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
|
||||
interface CountrySceneProps {
|
||||
message: string;
|
||||
emoji: string;
|
||||
data: any;
|
||||
data: {
|
||||
countries: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export default function CountryScene({ message, emoji, data }: CountrySceneProps) {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
const countries = data.countries as string[];
|
||||
|
||||
// Message animation (takes 1 second to appear)
|
||||
const messageOpacity = interpolate(
|
||||
frame,
|
||||
[240, 260],
|
||||
[0, 1],
|
||||
{ extrapolateRight: 'clamp' }
|
||||
);
|
||||
|
||||
const countries = useMemo(() => data.countries, [data.countries]);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: "100%",
|
||||
gap: 40
|
||||
}}>
|
||||
<p style={{
|
||||
fontSize: 40,
|
||||
color: "lightblue",
|
||||
marginTop: 40,
|
||||
textAlign: "center",
|
||||
padding: "0 20px",
|
||||
opacity: messageOpacity,
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: 20,
|
||||
gap: 10,
|
||||
width: "70%",
|
||||
gap: 20
|
||||
}}>
|
||||
{countries.map((country: string, index: number) => {
|
||||
// Start countries after message (1 second) with 0.3 second delay between each
|
||||
const delay = (240) + (index * 0.1 * fps);
|
||||
<span style={{
|
||||
fontSize: 100
|
||||
}}>
|
||||
{emoji}
|
||||
</span>
|
||||
<h1 style={{
|
||||
fontSize: 70,
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
margin: 0
|
||||
}}>
|
||||
{message}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: 20,
|
||||
justifyContent: "center",
|
||||
maxWidth: "80%"
|
||||
}}>
|
||||
{countries.map((country, index) => {
|
||||
const delay = index * 5;
|
||||
const scale = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
@@ -61,29 +65,21 @@ export default function CountryScene({ message, emoji, data }: CountrySceneProps
|
||||
});
|
||||
|
||||
return (
|
||||
<div key={country} style={{
|
||||
borderColor: "lightblue",
|
||||
borderRadius: "25px",
|
||||
height: 50,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
color: "lightblue",
|
||||
padding: "0px 20px",
|
||||
fontSize: 20,
|
||||
textAlign: "center",
|
||||
borderWidth: 1,
|
||||
borderStyle: "solid",
|
||||
transform: `scale(${scale})`,
|
||||
opacity: scale,
|
||||
}}>
|
||||
<div>
|
||||
<p style={{ margin: 0 }}>{country}</p>
|
||||
</div>
|
||||
<div
|
||||
key={country}
|
||||
style={{
|
||||
backgroundColor: "rgba(255,255,255,0.1)",
|
||||
padding: "10px 20px",
|
||||
borderRadius: 15,
|
||||
transform: `scale(${scale})`,
|
||||
opacity: scale,
|
||||
}}
|
||||
>
|
||||
<span style={{ color: "white", fontSize: 24 }}>{country}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
import React from 'react';
|
||||
import { Img, spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
|
||||
interface FriendsSceneProps {
|
||||
message: string;
|
||||
@@ -12,100 +11,129 @@ interface FriendsSceneProps {
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export default function FriendsScene({ message, emoji, data }: FriendsSceneProps) {
|
||||
const friends = useMemo(() => data.friends.map((friend, index) => ({
|
||||
name: friend.name,
|
||||
cover: friend.cover,
|
||||
})), [data.friends]);
|
||||
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
const initialDelay = useRef(frame);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
animation: "zoomIn 1s ease forwards",
|
||||
height: "100%",
|
||||
padding: "20px"
|
||||
}}>
|
||||
<p style={{
|
||||
fontSize: 70,
|
||||
padding: "0 70px",
|
||||
color: "lightblue",
|
||||
marginTop: 40,
|
||||
textAlign: "center",
|
||||
transition: "opacity 1s ease",
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: 20,
|
||||
marginBottom: 40,
|
||||
opacity: spring({
|
||||
frame,
|
||||
fps,
|
||||
from: 0,
|
||||
to: 1,
|
||||
config: {
|
||||
mass: 0.5,
|
||||
damping: 20,
|
||||
}
|
||||
})
|
||||
}}>
|
||||
{friends.map((friend, index) => {
|
||||
const delay = (initialDelay.current) + (index * 0.1 * fps);
|
||||
<span style={{
|
||||
fontSize: 80,
|
||||
transform: `translateY(${spring({
|
||||
frame,
|
||||
fps,
|
||||
from: 0,
|
||||
to: -10,
|
||||
config: {
|
||||
mass: 0.3,
|
||||
damping: 10,
|
||||
stiffness: 100
|
||||
}
|
||||
})}px)`
|
||||
}}>{emoji}</span>
|
||||
<h1 style={{
|
||||
fontSize: 50,
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
margin: 0,
|
||||
maxWidth: "80%",
|
||||
textShadow: "2px 2px 4px rgba(0,0,0,0.2)"
|
||||
}}>
|
||||
{message}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
display: "flex",
|
||||
gap: 30,
|
||||
justifyContent: "center",
|
||||
width: "100%"
|
||||
}}>
|
||||
{data.friends.map((friend, index) => {
|
||||
const delay = index * 5;
|
||||
const scale = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
from: 0,
|
||||
to: 1,
|
||||
config: {
|
||||
damping: 12,
|
||||
mass: 0.8,
|
||||
damping: 15,
|
||||
stiffness: 100
|
||||
},
|
||||
});
|
||||
|
||||
const rotation = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
from: 0,
|
||||
to: index % 2 === 0 ? 8 : -8,
|
||||
config: {
|
||||
mass: 0.5,
|
||||
damping: 20,
|
||||
stiffness: 80
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div key={index} style={{
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}>
|
||||
<img
|
||||
key={index}
|
||||
src={friend.cover}
|
||||
alt="memory"
|
||||
style={{
|
||||
width: 200,
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
borderRadius: "100%",
|
||||
margin: 10,
|
||||
transform: `scale(${scale})`,
|
||||
}}
|
||||
/>
|
||||
<p style={{
|
||||
fontSize: 20,
|
||||
textAlign: "center",
|
||||
marginTop: 10,
|
||||
color: "lightblue",
|
||||
}}>
|
||||
<div
|
||||
key={friend.name}
|
||||
style={{
|
||||
transform: `scale(${scale}) rotate(${rotation}deg)`,
|
||||
opacity: scale
|
||||
}}
|
||||
>
|
||||
<Img
|
||||
src={friend.cover}
|
||||
alt={friend.name}
|
||||
style={{
|
||||
width: 200,
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
borderRadius: "50%",
|
||||
border: "8px solid white",
|
||||
boxShadow: "0 8px 16px rgba(0,0,0,0.2)",
|
||||
}}
|
||||
/>
|
||||
<p style={{
|
||||
color: "white",
|
||||
fontSize: 24,
|
||||
textAlign: "center",
|
||||
margin: "15px 0",
|
||||
fontWeight: "bold",
|
||||
textShadow: "1px 1px 2px rgba(0,0,0,0.2)"
|
||||
}}>
|
||||
{friend.name}
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add this CSS to your global styles or a CSS-in-JS solution
|
||||
const styles = `
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Inject styles into the document
|
||||
const styleSheet = document.createElement("style");
|
||||
styleSheet.type = "text/css";
|
||||
styleSheet.innerText = styles;
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
import { Img, spring, useCurrentFrame, useVideoConfig } from 'remotion';
|
||||
|
||||
interface MemoriesSceneProps {
|
||||
message: string;
|
||||
@@ -11,60 +11,113 @@ interface MemoriesSceneProps {
|
||||
export default function MemoriesScene({ message, emoji, data }: MemoriesSceneProps) {
|
||||
const images = useMemo(() => data.images.map((image, index) => ({
|
||||
src: image,
|
||||
rotate: `${(index % 2 === 0 ? 1 : -1) * Math.random() * 10}deg`,
|
||||
rotate: (index % 2 === 0 ? 1 : -1) * 8,
|
||||
})), [data.images]);
|
||||
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
const initialDelay = useRef(frame);
|
||||
|
||||
const messageOpacity = spring({
|
||||
frame,
|
||||
fps,
|
||||
from: 0,
|
||||
to: 1,
|
||||
config: {
|
||||
mass: 0.5,
|
||||
damping: 20,
|
||||
stiffness: 100
|
||||
}
|
||||
});
|
||||
|
||||
const messageY = spring({
|
||||
frame,
|
||||
fps,
|
||||
from: -20,
|
||||
to: 0,
|
||||
config: {
|
||||
mass: 0.5,
|
||||
damping: 20,
|
||||
stiffness: 100
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
animation: "zoomIn 1s ease forwards",
|
||||
height: "100%",
|
||||
padding: "20px 0"
|
||||
}}>
|
||||
<p style={{
|
||||
fontSize: 70,
|
||||
padding: "0 70px",
|
||||
color: "lightblue",
|
||||
marginTop: 40,
|
||||
textAlign: "center",
|
||||
transition: "opacity 1s ease",
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: 10,
|
||||
opacity: messageOpacity,
|
||||
transform: `translateY(${messageY}px)`,
|
||||
}}>
|
||||
{images.map((image, index) => {
|
||||
const delay = (initialDelay.current) + (index * 0.1 * fps);
|
||||
<span style={{
|
||||
fontSize: 80,
|
||||
display: "block",
|
||||
textAlign: "center",
|
||||
marginBottom: 20
|
||||
}}>{emoji}</span>
|
||||
<p style={{
|
||||
fontSize: 50,
|
||||
padding: "0 40px",
|
||||
color: "white",
|
||||
marginBottom: 40,
|
||||
textAlign: "center",
|
||||
textShadow: "2px 2px 4px rgba(0,0,0,0.2)"
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
<div style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gap: 30,
|
||||
maxWidth: "90%",
|
||||
placeItems: "center",
|
||||
}}>
|
||||
{images.slice(0, 4).map((image, index) => {
|
||||
const delay = index * 5;
|
||||
const scale = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
from: 0,
|
||||
to: 1,
|
||||
config: {
|
||||
damping: 12,
|
||||
mass: 0.8,
|
||||
damping: 15,
|
||||
stiffness: 100
|
||||
},
|
||||
});
|
||||
|
||||
const rotation = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
from: 0,
|
||||
to: image.rotate, // Use the stable rotation value directly
|
||||
config: {
|
||||
mass: 0.5,
|
||||
damping: 20,
|
||||
stiffness: 80
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<img
|
||||
<Img
|
||||
key={index}
|
||||
src={image.src}
|
||||
alt="memory"
|
||||
style={{
|
||||
width: 200,
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
borderRadius: 10,
|
||||
margin: 10,
|
||||
rotate: image.rotate,
|
||||
transform: `scale(${scale})`,
|
||||
width: 280,
|
||||
height: 280,
|
||||
objectFit: "cover",
|
||||
borderRadius: 15,
|
||||
transform: `scale(${scale}) rotate(${rotation}deg)`,
|
||||
opacity: scale,
|
||||
boxShadow: "0 8px 16px rgba(0,0,0,0.3)",
|
||||
border: "8px solid white"
|
||||
}}
|
||||
/>
|
||||
)
|
||||
@@ -73,23 +126,3 @@ export default function MemoriesScene({ message, emoji, data }: MemoriesScenePro
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Add this CSS to your global styles or a CSS-in-JS solution
|
||||
const styles = `
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Inject styles into the document
|
||||
const styleSheet = document.createElement("style");
|
||||
styleSheet.type = "text/css";
|
||||
styleSheet.innerText = styles;
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
@@ -1,58 +1,81 @@
|
||||
import React from 'react'
|
||||
import { spring, useCurrentFrame, useVideoConfig, interpolate } from 'remotion'
|
||||
|
||||
interface WelcomeSceneProps {
|
||||
message: string;
|
||||
emoji: string;
|
||||
}
|
||||
|
||||
export default function WelcomeScene({ message, emoji }: WelcomeSceneProps) {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const scale = spring({
|
||||
frame,
|
||||
fps,
|
||||
from: 0.5,
|
||||
to: 1,
|
||||
config: { damping: 12 }
|
||||
});
|
||||
|
||||
const opacity = spring({
|
||||
frame,
|
||||
fps,
|
||||
from: 0,
|
||||
to: 1,
|
||||
config: { damping: 12 }
|
||||
});
|
||||
|
||||
const rotation = spring({
|
||||
frame,
|
||||
fps,
|
||||
from: -5,
|
||||
to: 0,
|
||||
config: { damping: 12 }
|
||||
});
|
||||
|
||||
const hue = interpolate(
|
||||
frame,
|
||||
[0, 60],
|
||||
[180, 240],
|
||||
{ extrapolateRight: 'clamp' }
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
animation: "zoomIn 1s ease forwards",
|
||||
transform: `scale(${scale})`,
|
||||
opacity: opacity,
|
||||
background: `radial-gradient(circle, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 100%)`,
|
||||
padding: 40,
|
||||
borderRadius: 20,
|
||||
}}>
|
||||
<p style={{
|
||||
fontSize: 100,
|
||||
color: "lightblue",
|
||||
fontSize: 120,
|
||||
marginTop: 40,
|
||||
marginBottom: 0,
|
||||
textAlign: "center",
|
||||
transition: "opacity 1s ease",
|
||||
transform: `translateY(${Math.sin(frame / 30) * 10}px) rotate(${rotation}deg)`,
|
||||
textShadow: '0 0 20px rgba(255,255,255,0.5)',
|
||||
}}>
|
||||
{emoji}
|
||||
</p>
|
||||
<p style={{
|
||||
fontSize: 70,
|
||||
fontSize: 80,
|
||||
padding: "0 70px",
|
||||
color: "lightblue",
|
||||
marginTop: 0,
|
||||
textAlign: "center",
|
||||
transition: "opacity 1s ease",
|
||||
color: `hsl(${hue}, 80%, 75%)`,
|
||||
marginTop: 20,
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
textShadow: '0 0 15px rgba(255,255,255,0.3)',
|
||||
letterSpacing: "2px",
|
||||
lineHeight: 1.2
|
||||
}}>
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Add this CSS to your global styles or a CSS-in-JS solution
|
||||
const styles = `
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Inject styles into the document
|
||||
const styleSheet = document.createElement("style");
|
||||
styleSheet.type = "text/css";
|
||||
styleSheet.innerText = styles;
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
Reference in New Issue
Block a user