@evatril/video-templates 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/video-images/03022026-bg-2.webp +0 -0
- package/public/video-images/03022026-bg-3.webp +0 -0
- package/public/video-images/03022026-bg-4.webp +0 -0
- package/public/video-images/03022026-bg-5.webp +0 -0
- package/public/video-images/03022026-bg.webp +0 -0
- package/public/video-images/03022026-krishnaradha-2.webp +0 -0
- package/public/video-images/03022026-krishnaradha-4.webp +0 -0
- package/public/video-images/03022026-krishnaradha-5.webp +0 -0
- package/public/video-images/03022026-krishnaradha.webp +0 -0
- package/public/video-images/28012026-BottomLeftFlower.webp +0 -0
- package/public/video-images/28012026-BottomRightFlower.webp +0 -0
- package/public/video-images/28012026-FlowerBorder.webp +0 -0
- package/public/video-images/28012026-Ganesh.webp +0 -0
- package/public/video-images/28012026-TopBorder.webp +0 -0
- package/public/video-images/28012026-TopLeftFlower.webp +0 -0
- package/public/video-images/28012026-TopRightFlower.webp +0 -0
- package/public/video-images/28012026-bg.webp +0 -0
- package/public/video-images/28012026-border.webp +0 -0
- package/public/video-images/28012026-frame.webp +0 -0
- package/public/video-images/wedding2.mp3 +0 -0
- package/src/Invitations/Elements/BlowingLeaves28012026.jsx +68 -0
- package/src/Invitations/Elements/FlowerReveal_TL_BR_28012026.jsx +114 -0
- package/src/Invitations/Elements/FlowerReveal_TR_BL_28012026.jsx +116 -0
- package/src/Invitations/Elements/GaneshBorder28012026.jsx +95 -0
- package/src/Invitations/Elements/GaneshGoldenHalo.jsx +90 -0
- package/src/Invitations/Elements/HeartDraw28012026.jsx +51 -0
- package/src/Invitations/Elements/HeartFlight28012026.jsx +72 -0
- package/src/Invitations/Elements/HoldSlide.jsx +103 -0
- package/src/Invitations/Elements/LetterReveal28012026.jsx +47 -0
- package/src/Invitations/Elements/PageFlipTransition.jsx +180 -0
- package/src/Invitations/Elements/{SmoothRevealFromTop.jsx → SmoothRevealFromTop20012026.jsx} +1 -1
- package/src/Invitations/Elements/WordReveal28012026.jsx +92 -0
- package/src/Invitations/Frames/F03022026_01.jsx +214 -0
- package/src/Invitations/Frames/F03022026_02.jsx +312 -0
- package/src/Invitations/Frames/F03022026_03.jsx +332 -0
- package/src/Invitations/Frames/F03022026_04.jsx +300 -0
- package/src/Invitations/Frames/F03022026_05.jsx +235 -0
- package/src/Invitations/Frames/F20012026_01.jsx +0 -2
- package/src/Invitations/Frames/F20012026_02.jsx +8 -8
- package/src/Invitations/Frames/F20012026_03.jsx +8 -8
- package/src/Invitations/Frames/F28012026_01.jsx +51 -0
- package/src/Invitations/Frames/F28012026_02.jsx +246 -0
- package/src/Invitations/Frames/F28012026_03.jsx +268 -0
- package/src/Invitations/Frames/F28012026_04.jsx +275 -0
- package/src/Invitations/Frames/F28012026_05.jsx +179 -0
- package/src/Invitations/Themes/T03022026_01.jsx +269 -0
- package/src/Invitations/Themes/T20012026_01.jsx +21 -3
- package/src/Invitations/Themes/T28012026_01.jsx +241 -0
- package/src/compositions.jsx +20 -2
- package/src/index.js +3 -1
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { useCurrentFrame, useVideoConfig, interpolate } from "remotion";
|
|
3
|
+
|
|
4
|
+
export const BlowingLeaves28012026 = ({ startAfter = 2, count = 30 }) => {
|
|
5
|
+
const frame = useCurrentFrame();
|
|
6
|
+
const { fps = 30 } = useVideoConfig();
|
|
7
|
+
|
|
8
|
+
const delayFrames = fps * startAfter;
|
|
9
|
+
|
|
10
|
+
// 🍃 Generate leaves once
|
|
11
|
+
const leaves = useMemo(() => {
|
|
12
|
+
return Array.from({ length: count }).map(() => ({
|
|
13
|
+
x: Math.random() * 100,
|
|
14
|
+
y: Math.random() * 100,
|
|
15
|
+
size: 20 + Math.random() * 25,
|
|
16
|
+
speedX: 0.3 + Math.random() * 0.8,
|
|
17
|
+
speedY: 0.1 + Math.random() * 0.4,
|
|
18
|
+
drift: 40 + Math.random() * 80,
|
|
19
|
+
rotateSpeed: 0.3 + Math.random() * 1,
|
|
20
|
+
phase: Math.random() * 200,
|
|
21
|
+
}));
|
|
22
|
+
}, [count]);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
{leaves.map((l, i) => {
|
|
27
|
+
const local = frame - delayFrames;
|
|
28
|
+
|
|
29
|
+
const appear = interpolate(local, [0, fps], [0, 1], {
|
|
30
|
+
extrapolateLeft: "clamp",
|
|
31
|
+
extrapolateRight: "clamp",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Horizontal flow
|
|
35
|
+
const moveX = ((local * l.speedX + l.phase) % 120) - 10;
|
|
36
|
+
|
|
37
|
+
// Gentle vertical float
|
|
38
|
+
const moveY =
|
|
39
|
+
l.y +
|
|
40
|
+
Math.sin((local + l.phase) / 40) * 20 +
|
|
41
|
+
local * l.speedY;
|
|
42
|
+
|
|
43
|
+
// Rotation
|
|
44
|
+
const rotate = Math.sin((local + l.phase) / 30) * 25;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
key={i}
|
|
49
|
+
style={{
|
|
50
|
+
position: "absolute",
|
|
51
|
+
left: `${moveX}%`,
|
|
52
|
+
top: `${moveY % 110}%`,
|
|
53
|
+
fontSize: l.size,
|
|
54
|
+
opacity: appear,
|
|
55
|
+
transform: `
|
|
56
|
+
translate(-50%, -50%)
|
|
57
|
+
rotate(${rotate}deg)
|
|
58
|
+
`,
|
|
59
|
+
pointerEvents: "none",
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
🍁
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
})}
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Img,
|
|
4
|
+
staticFile,
|
|
5
|
+
useCurrentFrame,
|
|
6
|
+
useVideoConfig,
|
|
7
|
+
interpolate,
|
|
8
|
+
Easing,
|
|
9
|
+
} from "remotion";
|
|
10
|
+
|
|
11
|
+
export const FlowerReveal_TL_BR_28012026 = ({ startAfter = 0 }) => {
|
|
12
|
+
const frame = useCurrentFrame();
|
|
13
|
+
const { fps } = useVideoConfig();
|
|
14
|
+
|
|
15
|
+
const delayFrames = fps * startAfter;
|
|
16
|
+
const bloomDuration = fps * 2.5; // 🌸 slower cinematic bloom
|
|
17
|
+
const localFrame = frame - delayFrames;
|
|
18
|
+
|
|
19
|
+
const progress = interpolate(localFrame, [0, bloomDuration], [0, 1], {
|
|
20
|
+
extrapolateRight: "clamp",
|
|
21
|
+
easing: Easing.out(Easing.cubic),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// 🌿 Opacity
|
|
25
|
+
const opacity = interpolate(localFrame, [0, bloomDuration * 0.5], [0, 1], {
|
|
26
|
+
extrapolateLeft: "clamp",
|
|
27
|
+
extrapolateRight: "clamp",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// 🌷 Scale
|
|
31
|
+
const scale = interpolate(localFrame, [0, bloomDuration], [0.6, 1], {
|
|
32
|
+
extrapolateLeft: "clamp",
|
|
33
|
+
extrapolateRight: "clamp",
|
|
34
|
+
easing: Easing.out(Easing.cubic),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 🌺 Gentle settle
|
|
38
|
+
const settle = interpolate(
|
|
39
|
+
localFrame,
|
|
40
|
+
[bloomDuration * 0.7, bloomDuration],
|
|
41
|
+
[1.04, 1],
|
|
42
|
+
{
|
|
43
|
+
extrapolateRight: "clamp",
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// 🍃 Slide in from corners
|
|
48
|
+
const slideTLX = interpolate(localFrame, [0, bloomDuration], [-180, 0], {
|
|
49
|
+
extrapolateRight: "clamp",
|
|
50
|
+
easing: Easing.out(Easing.cubic),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const slideTLY = interpolate(localFrame, [0, bloomDuration], [-180, 0], {
|
|
54
|
+
extrapolateRight: "clamp",
|
|
55
|
+
easing: Easing.out(Easing.cubic),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const slideBRX = interpolate(localFrame, [0, bloomDuration], [180, 0], {
|
|
59
|
+
extrapolateRight: "clamp",
|
|
60
|
+
easing: Easing.out(Easing.cubic),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const slideBRY = interpolate(localFrame, [0, bloomDuration], [180, 0], {
|
|
64
|
+
extrapolateRight: "clamp",
|
|
65
|
+
easing: Easing.out(Easing.cubic),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 🌿 Organic sway
|
|
69
|
+
const swing = Math.sin(frame / 18) * 0.6;
|
|
70
|
+
|
|
71
|
+
const finalScale = scale * settle;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<>
|
|
75
|
+
{/* 🌸 TOP LEFT */}
|
|
76
|
+
<Img
|
|
77
|
+
src={staticFile("video-images/28012026-TopLeftFlower.webp")}
|
|
78
|
+
style={{
|
|
79
|
+
position: "absolute",
|
|
80
|
+
top: "-170px",
|
|
81
|
+
left: "-50px",
|
|
82
|
+
width: "100%",
|
|
83
|
+
opacity,
|
|
84
|
+
transformOrigin: "top left",
|
|
85
|
+
transform: `
|
|
86
|
+
translate(${slideTLX}px, ${slideTLY}px)
|
|
87
|
+
scale(${finalScale})
|
|
88
|
+
rotate(${-swing}deg)
|
|
89
|
+
`,
|
|
90
|
+
pointerEvents: "none",
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
|
|
94
|
+
{/* 🌸 BOTTOM RIGHT */}
|
|
95
|
+
<Img
|
|
96
|
+
src={staticFile("video-images/28012026-BottomRightFlower.webp")}
|
|
97
|
+
style={{
|
|
98
|
+
position: "absolute",
|
|
99
|
+
bottom: "-300px",
|
|
100
|
+
right: -10,
|
|
101
|
+
width: "100%",
|
|
102
|
+
opacity,
|
|
103
|
+
transformOrigin: "bottom right",
|
|
104
|
+
transform: `
|
|
105
|
+
translate(${slideBRX}px, ${slideBRY}px)
|
|
106
|
+
scale(${finalScale})
|
|
107
|
+
rotate(${swing}deg)
|
|
108
|
+
`,
|
|
109
|
+
pointerEvents: "none",
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
</>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Img,
|
|
4
|
+
staticFile,
|
|
5
|
+
useCurrentFrame,
|
|
6
|
+
useVideoConfig,
|
|
7
|
+
interpolate,
|
|
8
|
+
Easing,
|
|
9
|
+
} from "remotion";
|
|
10
|
+
|
|
11
|
+
export const FlowerReveal_TR_BL_28012026 = () => {
|
|
12
|
+
const frame = useCurrentFrame();
|
|
13
|
+
const { fps } = useVideoConfig();
|
|
14
|
+
|
|
15
|
+
const bloomDuration = fps * 2.5;
|
|
16
|
+
|
|
17
|
+
// Main bloom progress
|
|
18
|
+
const progress = interpolate(frame, [0, bloomDuration], [0, 1], {
|
|
19
|
+
extrapolateRight: "clamp",
|
|
20
|
+
easing: Easing.out(Easing.quad),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// 🌿 Opacity
|
|
24
|
+
const opacity = interpolate(frame, [0, bloomDuration * 0.4], [0, 1], {
|
|
25
|
+
extrapolateRight: "clamp",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Bloom scale (petal opening feel)
|
|
29
|
+
const scale = interpolate(
|
|
30
|
+
frame,
|
|
31
|
+
[0, bloomDuration * 0.7, bloomDuration],
|
|
32
|
+
[0.4, 1.05, 1],
|
|
33
|
+
{
|
|
34
|
+
extrapolateRight: "clamp",
|
|
35
|
+
easing: Easing.out(Easing.cubic),
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// 🌺 Soft settle
|
|
40
|
+
const settle = interpolate(
|
|
41
|
+
frame,
|
|
42
|
+
[bloomDuration * 0.7, bloomDuration],
|
|
43
|
+
[1.04, 1],
|
|
44
|
+
{
|
|
45
|
+
extrapolateRight: "clamp",
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// 🍃 Slide positions
|
|
50
|
+
const slideTRX = interpolate(frame, [0, bloomDuration], [180, 0], {
|
|
51
|
+
extrapolateRight: "clamp",
|
|
52
|
+
easing: Easing.out(Easing.cubic),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const slideTRY = interpolate(frame, [0, bloomDuration], [-180, 0], {
|
|
56
|
+
extrapolateRight: "clamp",
|
|
57
|
+
easing: Easing.out(Easing.cubic),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const slideBLX = interpolate(frame, [0, bloomDuration], [-180, 0], {
|
|
61
|
+
extrapolateRight: "clamp",
|
|
62
|
+
easing: Easing.out(Easing.cubic),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const slideBLY = interpolate(frame, [0, bloomDuration], [180, 0], {
|
|
66
|
+
extrapolateRight: "clamp",
|
|
67
|
+
easing: Easing.out(Easing.cubic),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// 🌿 Gentle sway
|
|
71
|
+
const swing = Math.sin(frame / 18) * 0.6;
|
|
72
|
+
|
|
73
|
+
const finalScale = scale * settle;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<>
|
|
77
|
+
{/* 🌸 TOP RIGHT */}
|
|
78
|
+
<Img
|
|
79
|
+
src={staticFile("video-images/28012026-TopRightFlower.webp")}
|
|
80
|
+
style={{
|
|
81
|
+
position: "absolute",
|
|
82
|
+
top: "-130px",
|
|
83
|
+
right: 0,
|
|
84
|
+
width: "55%",
|
|
85
|
+
opacity,
|
|
86
|
+
transformOrigin: "top right",
|
|
87
|
+
transform: `
|
|
88
|
+
translate(${slideTRX}px, ${slideTRY}px)
|
|
89
|
+
scale(${finalScale})
|
|
90
|
+
rotate(${swing}deg)
|
|
91
|
+
`,
|
|
92
|
+
pointerEvents: "none",
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
{/* 🌸 BOTTOM LEFT */}
|
|
97
|
+
<Img
|
|
98
|
+
src={staticFile("video-images/28012026-BottomLeftFlower.webp")}
|
|
99
|
+
style={{
|
|
100
|
+
position: "absolute",
|
|
101
|
+
bottom: "-250px",
|
|
102
|
+
left: "-80px",
|
|
103
|
+
width: "100%",
|
|
104
|
+
opacity,
|
|
105
|
+
transformOrigin: "bottom left",
|
|
106
|
+
transform: `
|
|
107
|
+
translate(${slideBLX}px, ${slideBLY}px)
|
|
108
|
+
scale(${finalScale})
|
|
109
|
+
rotate(${-swing}deg)
|
|
110
|
+
`,
|
|
111
|
+
pointerEvents: "none",
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
</>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Img,
|
|
4
|
+
staticFile,
|
|
5
|
+
useCurrentFrame,
|
|
6
|
+
useVideoConfig,
|
|
7
|
+
interpolate,
|
|
8
|
+
Easing,
|
|
9
|
+
} from "remotion";
|
|
10
|
+
|
|
11
|
+
export const GaneshBorder28012026 = () => {
|
|
12
|
+
const frame = useCurrentFrame();
|
|
13
|
+
const { fps } = useVideoConfig();
|
|
14
|
+
|
|
15
|
+
const borderDelay = fps * 0.5; // 0.5 second delay
|
|
16
|
+
|
|
17
|
+
const borderProgress = interpolate(
|
|
18
|
+
frame,
|
|
19
|
+
[borderDelay, borderDelay + fps * 3],
|
|
20
|
+
[0, 1],
|
|
21
|
+
{
|
|
22
|
+
extrapolateLeft: "clamp",
|
|
23
|
+
extrapolateRight: "clamp",
|
|
24
|
+
easing: Easing.out(Easing.cubic),
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const borderScale = interpolate(borderProgress, [0, 1], [0.9, 1]);
|
|
30
|
+
const borderOpacity = borderProgress;
|
|
31
|
+
|
|
32
|
+
const ganeshProgress = interpolate(
|
|
33
|
+
frame,
|
|
34
|
+
[fps * 0.5, fps * 2.5],
|
|
35
|
+
[0, 1],
|
|
36
|
+
{
|
|
37
|
+
extrapolateLeft: "clamp",
|
|
38
|
+
extrapolateRight: "clamp",
|
|
39
|
+
easing: Easing.inOut(Easing.cubic),
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const ganeshScale = interpolate(ganeshProgress, [0, 1], [0.45, 1]);
|
|
44
|
+
const ganeshOpacity = ganeshProgress;
|
|
45
|
+
|
|
46
|
+
/* 🌿 Gentle border rotation */
|
|
47
|
+
// const rotate = Math.max(0, frame - delayFrames) * 0.20;
|
|
48
|
+
const rotate = frame * 0.15;
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
style={{
|
|
52
|
+
position: "absolute",
|
|
53
|
+
top: "10%",
|
|
54
|
+
width: "100%",
|
|
55
|
+
display: "flex",
|
|
56
|
+
justifyContent: "center",
|
|
57
|
+
pointerEvents: "none",
|
|
58
|
+
zIndex: 2,
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<div style={{ width: "100%", position: "relative" }}>
|
|
62
|
+
{/* 🌸 BORDER */}
|
|
63
|
+
<Img
|
|
64
|
+
src={staticFile("video-images/28012026-FlowerBorder.webp")}
|
|
65
|
+
style={{
|
|
66
|
+
width: "100%",
|
|
67
|
+
transformOrigin: "50% 50%",
|
|
68
|
+
opacity: borderOpacity,
|
|
69
|
+
transform: `
|
|
70
|
+
scale(${borderScale})
|
|
71
|
+
rotate(${rotate}deg)
|
|
72
|
+
`,
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
{/* 🕉 GANESH SMOOTH ENTRY */}
|
|
77
|
+
<Img
|
|
78
|
+
src={staticFile("video-images/28012026-Ganesh.webp")}
|
|
79
|
+
style={{
|
|
80
|
+
position: "absolute",
|
|
81
|
+
left: "53%",
|
|
82
|
+
top: "45%",
|
|
83
|
+
width: "55%",
|
|
84
|
+
opacity: ganeshOpacity,
|
|
85
|
+
transformOrigin: "50% 50%",
|
|
86
|
+
transform: `
|
|
87
|
+
translate(-50%, -50%)
|
|
88
|
+
scale(${ganeshScale})
|
|
89
|
+
`,
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Img,
|
|
4
|
+
staticFile,
|
|
5
|
+
useCurrentFrame,
|
|
6
|
+
useVideoConfig,
|
|
7
|
+
interpolate,
|
|
8
|
+
Easing,
|
|
9
|
+
} from "remotion";
|
|
10
|
+
|
|
11
|
+
export const GaneshGoldenHalo = () => {
|
|
12
|
+
const frame = useCurrentFrame();
|
|
13
|
+
const { fps } = useVideoConfig();
|
|
14
|
+
|
|
15
|
+
/* 🌸 HALO BLOOM FIRST */
|
|
16
|
+
const haloProgress = interpolate(frame, [0, fps * 2], [0, 1], {
|
|
17
|
+
extrapolateLeft: "clamp",
|
|
18
|
+
extrapolateRight: "clamp",
|
|
19
|
+
easing: Easing.inOut(Easing.cubic),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const haloScale = interpolate(haloProgress, [0, 1], [0, 1]);
|
|
23
|
+
|
|
24
|
+
/* 🕉 GANESH APPEARS AFTER HALO */
|
|
25
|
+
const ganeshDelay = fps * 1;
|
|
26
|
+
|
|
27
|
+
const ganeshProgress = interpolate(frame - ganeshDelay, [0, fps * 2], [0, 1], {
|
|
28
|
+
extrapolateLeft: "clamp",
|
|
29
|
+
extrapolateRight: "clamp",
|
|
30
|
+
easing: Easing.inOut(Easing.cubic),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const ganeshScale = interpolate(ganeshProgress, [0, 1], [0.45, 1]);
|
|
34
|
+
const ganeshOpacity = ganeshProgress;
|
|
35
|
+
|
|
36
|
+
/* 🌿 HALO ROTATION (LOCKED CENTER) */
|
|
37
|
+
const rotate = frame * 0.15;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
style={{
|
|
42
|
+
position: "absolute",
|
|
43
|
+
inset: 0,
|
|
44
|
+
display: "flex",
|
|
45
|
+
justifyContent: "center",
|
|
46
|
+
alignItems: "center",
|
|
47
|
+
pointerEvents: "none",
|
|
48
|
+
zIndex: 2,
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<div style={{ position: "relative", width: "100%", height: "100%" }}>
|
|
52
|
+
{/* 🌸 HALO (isolated rotation container) */}
|
|
53
|
+
<div
|
|
54
|
+
style={{
|
|
55
|
+
position: "absolute",
|
|
56
|
+
left: "50%",
|
|
57
|
+
top: "45%",
|
|
58
|
+
transform: "translate(-50%, -50%)",
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<Img
|
|
62
|
+
src={staticFile("video-images/30012026-Ganesh_golden_halo2.png")}
|
|
63
|
+
style={{
|
|
64
|
+
width: "100%",
|
|
65
|
+
transformOrigin: "50% 50%",
|
|
66
|
+
transform: `scale(${haloScale}) rotate(${rotate}deg)`,
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
{/* 🕉 GANESH */}
|
|
72
|
+
<Img
|
|
73
|
+
src={staticFile("video-images/28012026-Ganesh.png")}
|
|
74
|
+
style={{
|
|
75
|
+
position: "absolute",
|
|
76
|
+
left: "50%",
|
|
77
|
+
top: "55%",
|
|
78
|
+
width: "55%",
|
|
79
|
+
opacity: ganeshOpacity,
|
|
80
|
+
transformOrigin: "50% 50%",
|
|
81
|
+
transform: `
|
|
82
|
+
translate(-47%, -50%)
|
|
83
|
+
scale(${ganeshScale})
|
|
84
|
+
`,
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { useRef, useLayoutEffect, useState } from "react";
|
|
2
|
+
import { useCurrentFrame, interpolate, Easing } from "remotion";
|
|
3
|
+
|
|
4
|
+
export const HeartDraw28012026 = ({ startAfter = 30 }) => {
|
|
5
|
+
const frame = useCurrentFrame();
|
|
6
|
+
const pathRef = useRef(null);
|
|
7
|
+
const [length, setLength] = useState(0);
|
|
8
|
+
|
|
9
|
+
// Measure BEFORE paint (no blink)
|
|
10
|
+
useLayoutEffect(() => {
|
|
11
|
+
if (pathRef.current) {
|
|
12
|
+
const total = pathRef.current.getTotalLength();
|
|
13
|
+
setLength(total);
|
|
14
|
+
}
|
|
15
|
+
}, []);
|
|
16
|
+
|
|
17
|
+
const localFrame = frame - startAfter;
|
|
18
|
+
|
|
19
|
+
const progress = interpolate(localFrame, [0, 40], [0, 1], {
|
|
20
|
+
extrapolateLeft: "clamp",
|
|
21
|
+
extrapolateRight: "clamp",
|
|
22
|
+
easing: Easing.out(Easing.ease),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<svg
|
|
27
|
+
width="720"
|
|
28
|
+
height="700"
|
|
29
|
+
viewBox="0 0 512 512"
|
|
30
|
+
style={{
|
|
31
|
+
position: "absolute",
|
|
32
|
+
zIndex: 0,
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<path
|
|
36
|
+
ref={pathRef}
|
|
37
|
+
d="M256 448s-168-104-168-240c0-53 43-96 96-96 33 0 62 16 72 40 10-24 39-40 72-40 53 0 96 43 96 96 0 136-168 240-168 240z"
|
|
38
|
+
fill="none"
|
|
39
|
+
stroke="#D4A24C"
|
|
40
|
+
strokeWidth={8}
|
|
41
|
+
strokeLinecap="round"
|
|
42
|
+
strokeLinejoin="round"
|
|
43
|
+
strokeDasharray={length || 1}
|
|
44
|
+
strokeDashoffset={(length || 1) * (1 - progress)}
|
|
45
|
+
style={{
|
|
46
|
+
opacity: length ? 1 : 0, // 👈 hide until measured
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
</svg>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useCurrentFrame, useVideoConfig, interpolate, Easing } from "remotion";
|
|
3
|
+
|
|
4
|
+
export const HeartFlight28012026 = ({
|
|
5
|
+
emoji = "💖",
|
|
6
|
+
startAfter = 3,
|
|
7
|
+
}) => {
|
|
8
|
+
const frame = useCurrentFrame();
|
|
9
|
+
const { fps, width, height } = useVideoConfig();
|
|
10
|
+
|
|
11
|
+
const GLOBAL_DELAY = fps * startAfter;
|
|
12
|
+
|
|
13
|
+
const hearts = [
|
|
14
|
+
{ sx: 0.1, sy: 0.9, ex: 0.8, ey: 0.2, delay: 0 },
|
|
15
|
+
{ sx: 0.9, sy: 0.85, ex: 0.2, ey: 0.1, delay: 20 },
|
|
16
|
+
{ sx: 0.3, sy: 1.0, ex: 0.7, ey: 0.3, delay: 40 },
|
|
17
|
+
{ sx: 0.4, sy: 0.9, ex: 0.8, ey: 0.2, delay: 10 },
|
|
18
|
+
{ sx: 0.5, sy: 0.85, ex: 0.2, ey: 0.1, delay: 30 },
|
|
19
|
+
{ sx: 0.8, sy: 1.0, ex: 0.7, ey: 0.3, delay: 50 },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
{hearts.map((h, i) => {
|
|
25
|
+
const localFrame = frame - GLOBAL_DELAY - h.delay;
|
|
26
|
+
|
|
27
|
+
const progress = interpolate(localFrame, [0, fps * 6], [0, 1], {
|
|
28
|
+
extrapolateLeft: "clamp",
|
|
29
|
+
extrapolateRight: "clamp",
|
|
30
|
+
easing: Easing.inOut(Easing.ease),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const x = interpolate(progress, [0, 1], [
|
|
34
|
+
h.sx * width,
|
|
35
|
+
h.ex * width,
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
const y =
|
|
39
|
+
interpolate(progress, [0, 1], [
|
|
40
|
+
h.sy * height,
|
|
41
|
+
h.ey * height,
|
|
42
|
+
]) +
|
|
43
|
+
Math.sin(frame / 10 + i * 20) * 25;
|
|
44
|
+
|
|
45
|
+
const scale = interpolate(progress, [0, 0.1, 0.9, 1], [0, 1, 1, 0.6]);
|
|
46
|
+
|
|
47
|
+
const opacity = progress > 0.05 && progress < 0.95 ? 1 : 0;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
key={i}
|
|
52
|
+
style={{
|
|
53
|
+
position: "absolute",
|
|
54
|
+
left: x,
|
|
55
|
+
top: y,
|
|
56
|
+
fontSize: 70,
|
|
57
|
+
opacity,
|
|
58
|
+
transform: `
|
|
59
|
+
translate(-50%, -50%)
|
|
60
|
+
scale(${scale})
|
|
61
|
+
rotate(${Math.sin(localFrame / 15 + i) * 15}deg)
|
|
62
|
+
`,
|
|
63
|
+
pointerEvents: "none",
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{emoji}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
})}
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
};
|