fix: adapt to vertical resolution and fix flickering

This commit is contained in:
sai80082
2024-12-02 12:44:28 +05:30
parent 7f359c10d7
commit 8312fc183d
5 changed files with 341 additions and 270 deletions
+62 -71
View File
@@ -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);
+48 -52
View File
@@ -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>
)
);
}
+98 -70
View File
@@ -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);
+81 -48
View File
@@ -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);
+52 -29
View File
@@ -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);