├── .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 | Animated Remotion Logo 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 | 50 | 56 | 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 | 13 | 17 | 21 | 25 | 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 | --------------------------------------------------------------------------------