├── .eslintrc
├── .gitignore
├── .vscode
└── settings.json
├── README.md
├── bun.lockb
├── package.json
├── public
└── pitch.png
├── remotion.config.ts
├── src
├── Composition.tsx
├── Overlay.tsx
├── Perspective.tsx
├── Ray.tsx
├── Root.tsx
├── ScaleIn.tsx
├── SwitzerlandLogo.tsx
└── index.ts
└── tsconfig.json
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@remotion",
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .DS_Store
4 | .env
5 |
6 | # Ignore the output video from Git but not videos you import into src/.
7 | out
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "typescript.enablePromptUseWorkspaceTsdk": true
4 | }
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Remotion video
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Welcome to your Remotion project!
13 |
14 | ## Commands
15 |
16 | **Install Dependencies**
17 |
18 | ```console
19 | bun install
20 | ```
21 |
22 | **Start Preview**
23 |
24 | ```console
25 | bun start
26 | ```
27 |
28 | **Render video**
29 |
30 | ```console
31 | bun run build
32 | ```
33 |
34 | **Upgrade Remotion**
35 |
36 | ```console
37 | bun run upgrade
38 | ```
39 |
40 | ## Docs
41 |
42 | Get started with Remotion by reading the [fundamentals page](https://www.remotion.dev/docs/the-fundamentals).
43 |
44 | ## Help
45 |
46 | We provide help on our [Discord server](https://discord.gg/6VzzNDwUwV).
47 |
48 | ## Issues
49 |
50 | Found an issue with Remotion? [File an issue here](https://github.com/remotion-dev/remotion/issues/new).
51 |
52 | ## License
53 |
54 | Note that for some entities a company license is needed. [Read the terms here](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md).
55 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonnyBurger/euro-2024-animation/8aa240890ff39e076e0d67e083bddf99b4f7154e/bun.lockb
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "euro",
3 | "version": "1.0.0",
4 | "description": "My Remotion video",
5 | "repository": {},
6 | "license": "UNLICENSED",
7 | "dependencies": {
8 | "@remotion/cli": "4.0.174",
9 | "@remotion/google-fonts": "^4.0.174",
10 | "@remotion/paths": "^4.0.174",
11 | "@remotion/shapes": "^4.0.174",
12 | "react": "^18.0.0",
13 | "react-dom": "^18.0.0",
14 | "remotion": "4.0.174"
15 | },
16 | "devDependencies": {
17 | "@remotion/eslint-config": "4.0.174",
18 | "@types/react": "^18.0.26",
19 | "@types/web": "^0.0.143",
20 | "eslint": "^8.43.0",
21 | "prettier": "^3.2.5",
22 | "typescript": "^5.4.5"
23 | },
24 | "scripts": {
25 | "start": "remotionb studio",
26 | "build": "remotionb render MyComp out/video.mp4",
27 | "upgrade": "remotionb upgrade",
28 | "test": "eslint src --ext ts,tsx,js,jsx && tsc"
29 | },
30 | "packageManager": "bun@1.1.12"
31 | }
--------------------------------------------------------------------------------
/public/pitch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JonnyBurger/euro-2024-animation/8aa240890ff39e076e0d67e083bddf99b4f7154e/public/pitch.png
--------------------------------------------------------------------------------
/remotion.config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Note: When using the Node.JS APIs, the config file
3 | * doesn't apply. Instead, pass options directly to the APIs.
4 | *
5 | * All configuration options: https://remotion.dev/docs/config
6 | */
7 |
8 | import { Config } from "@remotion/cli/config";
9 |
10 | Config.setVideoImageFormat("jpeg");
11 | Config.setOverwriteOutput(true);
12 |
--------------------------------------------------------------------------------
/src/Composition.tsx:
--------------------------------------------------------------------------------
1 | import { AbsoluteFill, Img, interpolate, staticFile } from "remotion";
2 | import { useCurrentFrame } from "remotion";
3 | import { random, spring, useVideoConfig } from "remotion";
4 | import { FINAL_RADIUS, Ray } from "./Ray";
5 | import { Perspective } from "./Perspective";
6 | import { ScaleIn } from "./ScaleIn";
7 | import { Overlay } from "./Overlay";
8 |
9 | const colors = [
10 | "#24BB5D",
11 | "#020101",
12 | "#F2C004",
13 | "#F00E03",
14 | "#F2F0EE",
15 | "#28BA61",
16 | "#033BE0",
17 | "#F4F0F3",
18 | ];
19 |
20 | const SEGMENTS = 66;
21 | const singlesegmentLength = 1 / SEGMENTS;
22 |
23 | export const MyComposition = () => {
24 | const { fps } = useVideoConfig();
25 | const frame = useCurrentFrame();
26 | return (
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 | {new Array(SEGMENTS).fill(true).map((_, i) => {
38 | const prog = spring({
39 | fps,
40 | frame,
41 | config: {
42 | damping: 200,
43 | },
44 | delay: random(i) * 5,
45 | });
46 | const rotation = (i / SEGMENTS) * 2 * Math.PI + (Math.PI / 3) * 2;
47 |
48 | const initialRadius =
49 | i > SEGMENTS / 3
50 | ? FINAL_RADIUS
51 | : random(i) * 0.1 * FINAL_RADIUS;
52 | const radius = interpolate(
53 | prog,
54 | [0, 1],
55 | [initialRadius, FINAL_RADIUS]
56 | );
57 |
58 | return (
59 |
67 | );
68 | })}
69 |
70 | {new Array(SEGMENTS / 3).fill(true).map((_, i) => {
71 | const progress = (delay: number, initialProgress: number) =>
72 | spring({
73 | fps,
74 | frame,
75 | config: {
76 | damping: 200,
77 | },
78 | from: initialProgress,
79 | to: 1,
80 | delay,
81 | });
82 |
83 | const sliceLength =
84 | i % 2 === 0 ? singlesegmentLength * 2 : singlesegmentLength;
85 | const initialProgress = random(i) * 0.3;
86 | const color = colors[i % colors.length];
87 | const delay = random(i) * 10;
88 | const prog = progress(delay, initialProgress);
89 | const rotation = (i / SEGMENTS) * 2 * Math.PI + (Math.PI / 3) * 2;
90 | const absoluteRadius = random(i) + 0.4 * FINAL_RADIUS;
91 | const radius = interpolate(
92 | prog,
93 | [0, 1],
94 | [absoluteRadius, FINAL_RADIUS]
95 | );
96 |
97 | const strokeWidth = interpolate(prog, [0, 1], [absoluteRadius, 12]);
98 |
99 | return (
100 |
108 | );
109 | })}
110 |
111 |
112 |
113 |
114 | );
115 | };
116 |
--------------------------------------------------------------------------------
/src/Overlay.tsx:
--------------------------------------------------------------------------------
1 | import { Easing, interpolate } from "remotion";
2 | import { useCurrentFrame } from "remotion";
3 | import React from "react";
4 | import { AbsoluteFill } from "remotion";
5 | import { loadFont, fontFamily } from "@remotion/google-fonts/LeagueGothic";
6 | import {
7 | loadFont as loadMontserrat,
8 | fontFamily as montserrat,
9 | } from "@remotion/google-fonts/Montserrat";
10 | import { SwitzerlandLogo } from "./SwitzerlandLogo";
11 |
12 | loadFont();
13 | loadMontserrat("normal");
14 |
15 | export const Overlay: React.FC = () => {
16 | const frame = useCurrentFrame();
17 | const progress = interpolate(frame, [5, 20], [0, 1], {
18 | extrapolateRight: "clamp",
19 | extrapolateLeft: "clamp",
20 | easing: Easing.in(Easing.ease),
21 | });
22 |
23 | const opacity = interpolate(progress, [0, 1], [0, 1]);
24 | const translationY = interpolate(progress, [0, 1], [50, 0]);
25 |
26 | return (
27 |
36 |
37 |
38 |
44 | SWITZERLAND
45 |
46 |
47 |
55 | HEAD COACH
56 |
57 |
64 | MURAT YAKIN
65 |
66 |
67 | );
68 | };
69 |
--------------------------------------------------------------------------------
/src/Perspective.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { AbsoluteFill } from "remotion";
3 |
4 | export const Perspective: React.FC<{
5 | children: React.ReactNode;
6 | }> = ({ children }) => {
7 | return (
8 |
13 |
18 | {children}
19 |
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/src/Ray.tsx:
--------------------------------------------------------------------------------
1 | import { AbsoluteFill } from "remotion";
2 | import React, { useMemo } from "react";
3 | import { PathInternals, getLength } from "@remotion/paths";
4 | import { makeCircle } from "@remotion/shapes";
5 |
6 | export const FINAL_RADIUS = 720;
7 |
8 | export const Ray: React.FC<{
9 | i: number;
10 | color: string;
11 | sliceLength: number;
12 | rotation: number;
13 | radius: number;
14 | strokeWidth: number;
15 | }> = ({ color, i, sliceLength, rotation, radius, strokeWidth }) => {
16 | const circle = useMemo(() => {
17 | return makeCircle({
18 | radius: radius - strokeWidth / 2,
19 | });
20 | }, [radius, strokeWidth]);
21 |
22 | const { path } = circle;
23 |
24 | const length = getLength(path);
25 |
26 | const pathLength = length * sliceLength;
27 |
28 | const cutPath = useMemo(() => {
29 | return PathInternals.cutPath(path, pathLength);
30 | }, [path, pathLength]);
31 |
32 | return (
33 |
40 |
57 |
58 | );
59 | };
60 |
--------------------------------------------------------------------------------
/src/Root.tsx:
--------------------------------------------------------------------------------
1 | import { Composition } from "remotion";
2 | import { MyComposition } from "./Composition";
3 |
4 | export const RemotionRoot: React.FC = () => {
5 | return (
6 | <>
7 |
15 | >
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/src/ScaleIn.tsx:
--------------------------------------------------------------------------------
1 | import { useCurrentFrame } from "remotion";
2 | import React from "react";
3 | import { AbsoluteFill, spring, useVideoConfig } from "remotion";
4 |
5 | export const ScaleIn: React.FC<{
6 | children: React.ReactNode;
7 | }> = ({ children }) => {
8 | const { fps } = useVideoConfig();
9 | const frame = useCurrentFrame();
10 | const scale = spring({
11 | fps,
12 | frame,
13 | config: {
14 | damping: 200,
15 | },
16 | });
17 | return (
18 |
19 | {children}
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/src/SwitzerlandLogo.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const SwitzerlandLogo: React.FC = () => {
4 | return (
5 |
26 | );
27 | };
28 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { registerRoot } from "remotion";
2 | import { RemotionRoot } from "./Root";
3 |
4 | registerRoot(RemotionRoot);
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "module": "commonjs",
5 | "jsx": "react-jsx",
6 | "outDir": "./dist",
7 | "strict": true,
8 | "noEmit": true,
9 | "lib": ["es2015"],
10 | "esModuleInterop": true,
11 | "skipLibCheck": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "noUnusedLocals": true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------