feat: add resume.pdf button
All checks were successful
Deploy to SFTP Server / build (push) Successful in 41m27s

This commit is contained in:
max_richter 2024-04-08 14:22:36 +02:00
parent e41ef2fceb
commit d1d6867130
12 changed files with 107 additions and 40 deletions

Binary file not shown.

View File

@ -10,14 +10,15 @@ const t = useTranslations(Astro.url);
--- ---
<Card <Card
classes="googley-eye-target relative rounded-diag-md border border-neutral bg-dark grid xs:grid-cols-[250px_1fr] min-h-[180px] sm:h-[180px] mt-8"> classes="googley-eye-target relative rounded-diag-md border border-neutral bg-dark grid xs:grid-cols-[200px_1fr] sm:grid-cols-[300px_1fr] mt-8">
<div <div
class="image relative h-[130%] self-end items-end flex overflow-hidden order-last xs:order-first"> class="relative xs:h-full self-end items-end flex order-last xs:order-first">
<div class="relative inline w-1/2 xs:w-full"> <div
class="image xs:absolute inline w-1/2 xs:w-full xs:h-[110%] overflow-hidden">
<Image <Image
src={MaxImg} src={MaxImg}
alt="its mee" alt="its mee"
class="object-bottom h-full object-cover" class="object-bottom h-full object-contain"
hash={false} hash={false}
maxWidth={700} maxWidth={700}
loader={false} loader={false}
@ -31,9 +32,15 @@ const t = useTranslations(Astro.url);
</div> </div>
</div> </div>
<div class="content flex flex-col p-8 pl-4 gap-2 justify-center"> <div class="content flex flex-col p-8 pl-4 gap-3 justify-center">
<h1 class="text-2xl">{t("home.title")}</h1> <h1 class="text-2xl">{t("home.title")}</h1>
<p>{t("home.subtitle")}</p> <p>{t("home.subtitle")}</p>
<a
class="bg gradient flex items-center border border-neutral gap-2 w-fit p-2 px-4 rounded-2xl"
href="/max-richter-resume.pdf">
{t("resume").toLowerCase()}.pdf
<span class="i-tabler-download w-4 h-4 dark:opacity-50"></span>
</a>
</div> </div>
</Card> </Card>

View File

@ -3,6 +3,7 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import IconSun from "~icons/tabler/Sun"; import IconSun from "~icons/tabler/Sun";
import IconMoon from "~icons/tabler/Moon"; import IconMoon from "~icons/tabler/Moon";
import { colors } from "@helpers/colors";
let theme = writable(""); let theme = writable("");
@ -10,8 +11,12 @@
document.documentElement.classList.remove("light", "dark"); document.documentElement.classList.remove("light", "dark");
document.documentElement.classList.add($theme); document.documentElement.classList.add($theme);
localStorage.setItem("theme", $theme); localStorage.setItem("theme", $theme);
// @ts-ignore
window["updateBackgroundColor"]?.(); const background = window.getComputedStyle(document.body);
$colors = {
background: background.backgroundColor,
};
} }
function toggleTheme() { function toggleTheme() {

View File

@ -2,38 +2,36 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import createFishes from "./fishes/webgl-fishes"; import createFishes from "./fishes/webgl-fishes";
import { Color } from "ogl"; import { Color } from "ogl";
import { rgbToHex } from "@helpers/colors"; import { colors, rgbToHex } from "@helpers/colors";
let canvasBottom: HTMLCanvasElement; let canvasBottom: HTMLCanvasElement;
let speed = 0; let speed = 0;
let timeOffset = Math.random() * 100000; let timeOffset = Math.random() * 100000;
let fishCanvasBack: { resize: any; update: any }; let fishCanvasBack: ReturnType<typeof createFishes>;
let render = true; let render = true;
const color = new Color("#ffffff"); const color = new Color("#ffffff");
function updateColor(c: string) {
const d = new Color(rgbToHex(c));
color.set(d.r, d.g, d.b);
fishCanvasBack?.resize();
}
$: if ($colors.background) {
updateColor($colors.background);
}
const handleResize = () => { const handleResize = () => {
fishCanvasBack.resize(); fishCanvasBack.resize();
render = window.innerWidth > 500; render = window.innerWidth > 500;
}; };
const updateBackgroundColor = () => {
const background = window.getComputedStyle(document.body);
const d = new Color(rgbToHex(background.backgroundColor));
color.set(d.r, d.g, d.b);
fishCanvasBack.resize();
};
let loaded = false; let loaded = false;
onMount(async () => { onMount(async () => {
const background = window.getComputedStyle(document.body);
const d = new Color(rgbToHex(background.backgroundColor));
color.set(d.r, d.g, d.b);
fishCanvasBack = createFishes(canvasBottom, { amount: 100, color }); fishCanvasBack = createFishes(canvasBottom, { amount: 100, color });
fishCanvasBack.resize(); fishCanvasBack.resize();
@ -45,8 +43,6 @@
render && fishCanvasBack.update(t, timeOffset); render && fishCanvasBack.update(t, timeOffset);
} }
loaded = true; loaded = true;
// @ts-ignore
window["updateBackgroundColor"] = updateBackgroundColor;
}); });
</script> </script>
@ -69,10 +65,10 @@
left: 0px; left: 0px;
z-index: -1; z-index: -1;
opacity: 0; opacity: 0;
transition: opacity 0.5s; transition: opacity 4s;
} }
canvas.loaded { canvas.loaded {
opacity: 0.2; opacity: 0.8;
} }
</style> </style>

View File

@ -3,6 +3,7 @@
import { createLeaves, setRotation } from "./leaves"; import { createLeaves, setRotation } from "./leaves";
import { Color } from "ogl"; import { Color } from "ogl";
import { rgbToHex } from "@helpers/colors"; import { rgbToHex } from "@helpers/colors";
import { colors } from "@helpers/colors";
let canvas: HTMLCanvasElement; let canvas: HTMLCanvasElement;
@ -14,17 +15,17 @@
const color = new Color("#000000"); const color = new Color("#000000");
const updateBackgroundColor = () => { function updateColor(c: string) {
const background = window.getComputedStyle(document.body); const d = new Color(rgbToHex(c));
const d = new Color(rgbToHex(background.backgroundColor));
color.set(d.r, d.g, d.b); color.set(d.r, d.g, d.b);
}; }
$: if ($colors.background) {
updateColor($colors.background);
}
onMount(() => { onMount(() => {
updateBackgroundColor(); createLeaves({ canvas, num: 40, minZ: 0, maxZ: 1, color });
createLeaves({ canvas, num: 20, minZ: 0, maxZ: 1, color });
// @ts-ignore
window["updateBackgroundColor"] = updateBackgroundColor;
setTimeout(() => { setTimeout(() => {
loaded = true; loaded = true;
}, 100); }, 100);
@ -48,10 +49,10 @@
z-index: -1; z-index: -1;
pointer-events: none; pointer-events: none;
opacity: 0; opacity: 0;
transition: opacity 2s; transition: opacity 4s;
} }
.loaded { .loaded {
opacity: 0.2; opacity: 0.6;
} }
</style> </style>

Binary file not shown.

View File

@ -0,0 +1,3 @@
[ZoneTransfer]
ZoneId=3
HostUrl=about:internet

View File

@ -16,6 +16,8 @@ Plantarium ist die Schnittmenge zwischen zwei Dingen die ich sehr faszinierend f
Es ist eine WebApp die es Nutzern ermöglicht Pflanzen zu erstellen und zu exportieren. Es ist eine WebApp die es Nutzern ermöglicht Pflanzen zu erstellen und zu exportieren.
Die User legen dabei über ein Node-System fest wie die Pflanze aussieht und Plantarium generiert daraus ein 3D Modell. Die User legen dabei über ein Node-System fest wie die Pflanze aussieht und Plantarium generiert daraus ein 3D Modell.
<Image src={plantarium_screenshot} alt="Plantarium Screenshot"/>
# Die Anfänge und Herausforderungen # Die Anfänge und Herausforderungen
Der erste Prototyp war innerhalb von zwei Wochen intensiver Arbeit fertig und sah ungefähr so aus: Der erste Prototyp war innerhalb von zwei Wochen intensiver Arbeit fertig und sah ungefähr so aus:
@ -33,6 +35,7 @@ import screenshot_geometry_nodes from "./images/screenshot-geometry-nodes.jpg"
import screenshot_houdini from "./images/screenshot-houdini.jpg" import screenshot_houdini from "./images/screenshot-houdini.jpg"
import screenshot_unreal from "./images/screenshot-unreal.jpg" import screenshot_unreal from "./images/screenshot-unreal.jpg"
import screenshot_davinci from "./images/screenshot-davinci.jpg" import screenshot_davinci from "./images/screenshot-davinci.jpg"
import plantarium_screenshot from "./images/plantarium-screenshot.png"
import Plantarium from "./images/plantarium.png" import Plantarium from "./images/plantarium.png"
import ImageGallery from "@components/ImageGallery.svelte" import ImageGallery from "@components/ImageGallery.svelte"
@ -40,6 +43,7 @@ import ImageGallery from "@components/ImageGallery.svelte"
<Leaves client:load/> <Leaves client:load/>
<ImageSlider title="Erster Prototyp" client:load> <ImageSlider title="Erster Prototyp" client:load>
<Image src={page01_0} alt="Stem Page"/> <Image src={page01_0} alt="Stem Page"/>
<Image src={page01_1} alt="Branches page"/> <Image src={page01_1} alt="Branches page"/>
@ -83,8 +87,6 @@ In der Beispielgrafik haben wir zwei `input-color` nodes die jeweils eine Farbe
Das coole ist das man dieses System sehr generisch gestalten kann und zum beispiel eine `generate-stem`, `generate-branches` oder eine `add-leaves` node programmieren kann. Aufgrund der Das coole ist das man dieses System sehr generisch gestalten kann und zum beispiel eine `generate-stem`, `generate-branches` oder eine `add-leaves` node programmieren kann. Aufgrund der
<Image src={Plantarium} alt="Plantariums uses nodes to create plants"/>
<ImageSlider title="Beispiele von Node Systemen" client:load> <ImageSlider title="Beispiele von Node Systemen" client:load>
<Image src={screenshot_geometry_nodes} alt="Blenders uses nodes to create geometry"/> <Image src={screenshot_geometry_nodes} alt="Blenders uses nodes to create geometry"/>
<Image src={screenshot_houdini} alt="Houdini uses nodes for vfx/simulations"/> <Image src={screenshot_houdini} alt="Houdini uses nodes for vfx/simulations"/>

9
src/env.d.ts vendored
View File

@ -1,3 +1,12 @@
/// <reference path="../.astro/types.d.ts" /> /// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" /> /// <reference types="astro/client" />
/// <reference types="unplugin-icons/types" /> /// <reference types="unplugin-icons/types" />
declare global {
interface Window {
colors: import("svelte/store").Writable<{
background: string;
}>
}
}

View File

@ -1,3 +1,5 @@
import { writable } from "svelte/store";
// function to turn css rgb() strings to hex // function to turn css rgb() strings to hex
export function rgbToHex(rgb: string) { export function rgbToHex(rgb: string) {
let hex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); let hex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
@ -12,3 +14,7 @@ export function rgbToHex(rgb: string) {
.join("") .join("")
); );
} }
export const colors = writable({
background: "#f0f0f0",
});

View File

@ -23,6 +23,7 @@ export const ui = {
'nav.videos': 'Videos', 'nav.videos': 'Videos',
'nav.photos': 'Photos', 'nav.photos': 'Photos',
'toc.title': 'Table of Contents', 'toc.title': 'Table of Contents',
"resume": "Resume",
}, },
de: { de: {
"en": "English", "en": "English",
@ -39,6 +40,7 @@ export const ui = {
'nav.projects': 'Projekte', 'nav.projects': 'Projekte',
'nav.videos': 'Videos', 'nav.videos': 'Videos',
'nav.photos': 'Fotos', 'nav.photos': 'Fotos',
"resume": "Lebenslauf",
'toc.title': 'Inhaltsverzeichnis', 'toc.title': 'Inhaltsverzeichnis',
}, },
} as const; } as const;

View File

@ -74,11 +74,44 @@ import "./global.css";
body { body {
max-width: 700px; max-width: 700px;
margin: 0 auto; margin: 0 auto;
position: relative;
} }
body > * { main,
header,
footer {
background: var(--background-dark); background: var(--background-dark);
padding: 0.5rem 3rem; padding: 0.5rem 3rem;
} }
body::after {
content: "";
position: fixed;
height: 100vh;
width: 200px;
top: 0;
transform: translateX(-100%);
background: red;
background: linear-gradient(
to left,
var(--background-dark),
transparent
);
}
main::before {
content: "";
position: absolute;
top: -200px;
right: -200px;
bottom: -100px;
width: 200px;
background: linear-gradient(
to right,
var(--background-dark),
transparent
);
}
@media (max-width: 700px) { @media (max-width: 700px) {
body > * { body > * {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
@ -90,10 +123,10 @@ import "./global.css";
<header class="sticky bottom-0 sm:top-0 z-2 order-last sm:order-first"> <header class="sticky bottom-0 sm:top-0 z-2 order-last sm:order-first">
<Nav /> <Nav />
</header> </header>
<main id="main-content" class="flex flex-col gap-4"> <main id="main-content" class="relative flex flex-col gap-6">
<slot /> <slot />
</main> </main>
<footer class="px-4 flex gap-8"> <footer class="mx-8 mb-4 mt-2 flex gap-8">
<LanguagePicker /> <LanguagePicker />
<a <a
href="https://git.max-richter.dev/max/website" href="https://git.max-richter.dev/max/website"