feat: add resume.pdf button
All checks were successful
Deploy to SFTP Server / build (push) Successful in 41m27s
All checks were successful
Deploy to SFTP Server / build (push) Successful in 41m27s
This commit is contained in:
parent
e41ef2fceb
commit
d1d6867130
BIN
public/max-richter-resume.pdf
Normal file
BIN
public/max-richter-resume.pdf
Normal file
Binary file not shown.
@ -10,14 +10,15 @@ const t = useTranslations(Astro.url);
|
||||
---
|
||||
|
||||
<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
|
||||
class="image relative h-[130%] self-end items-end flex overflow-hidden order-last xs:order-first">
|
||||
<div class="relative inline w-1/2 xs:w-full">
|
||||
class="relative xs:h-full self-end items-end flex order-last xs:order-first">
|
||||
<div
|
||||
class="image xs:absolute inline w-1/2 xs:w-full xs:h-[110%] overflow-hidden">
|
||||
<Image
|
||||
src={MaxImg}
|
||||
alt="its mee"
|
||||
class="object-bottom h-full object-cover"
|
||||
class="object-bottom h-full object-contain"
|
||||
hash={false}
|
||||
maxWidth={700}
|
||||
loader={false}
|
||||
@ -31,9 +32,15 @@ const t = useTranslations(Astro.url);
|
||||
</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>
|
||||
<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>
|
||||
</Card>
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
import { writable } from "svelte/store";
|
||||
import IconSun from "~icons/tabler/Sun";
|
||||
import IconMoon from "~icons/tabler/Moon";
|
||||
import { colors } from "@helpers/colors";
|
||||
|
||||
let theme = writable("");
|
||||
|
||||
@ -10,8 +11,12 @@
|
||||
document.documentElement.classList.remove("light", "dark");
|
||||
document.documentElement.classList.add($theme);
|
||||
localStorage.setItem("theme", $theme);
|
||||
// @ts-ignore
|
||||
window["updateBackgroundColor"]?.();
|
||||
|
||||
const background = window.getComputedStyle(document.body);
|
||||
|
||||
$colors = {
|
||||
background: background.backgroundColor,
|
||||
};
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
|
@ -2,38 +2,36 @@
|
||||
import { onMount } from "svelte";
|
||||
import createFishes from "./fishes/webgl-fishes";
|
||||
import { Color } from "ogl";
|
||||
import { rgbToHex } from "@helpers/colors";
|
||||
import { colors, rgbToHex } from "@helpers/colors";
|
||||
|
||||
let canvasBottom: HTMLCanvasElement;
|
||||
|
||||
let speed = 0;
|
||||
let timeOffset = Math.random() * 100000;
|
||||
|
||||
let fishCanvasBack: { resize: any; update: any };
|
||||
let fishCanvasBack: ReturnType<typeof createFishes>;
|
||||
let render = true;
|
||||
|
||||
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 = () => {
|
||||
fishCanvasBack.resize();
|
||||
|
||||
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;
|
||||
|
||||
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.resize();
|
||||
@ -45,8 +43,6 @@
|
||||
render && fishCanvasBack.update(t, timeOffset);
|
||||
}
|
||||
loaded = true;
|
||||
// @ts-ignore
|
||||
window["updateBackgroundColor"] = updateBackgroundColor;
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -69,10 +65,10 @@
|
||||
left: 0px;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
transition: opacity 4s;
|
||||
}
|
||||
|
||||
canvas.loaded {
|
||||
opacity: 0.2;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
|
@ -3,6 +3,7 @@
|
||||
import { createLeaves, setRotation } from "./leaves";
|
||||
import { Color } from "ogl";
|
||||
import { rgbToHex } from "@helpers/colors";
|
||||
import { colors } from "@helpers/colors";
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
|
||||
@ -14,17 +15,17 @@
|
||||
|
||||
const color = new Color("#000000");
|
||||
|
||||
const updateBackgroundColor = () => {
|
||||
const background = window.getComputedStyle(document.body);
|
||||
const d = new Color(rgbToHex(background.backgroundColor));
|
||||
function updateColor(c: string) {
|
||||
const d = new Color(rgbToHex(c));
|
||||
color.set(d.r, d.g, d.b);
|
||||
};
|
||||
}
|
||||
|
||||
$: if ($colors.background) {
|
||||
updateColor($colors.background);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
updateBackgroundColor();
|
||||
createLeaves({ canvas, num: 20, minZ: 0, maxZ: 1, color });
|
||||
// @ts-ignore
|
||||
window["updateBackgroundColor"] = updateBackgroundColor;
|
||||
createLeaves({ canvas, num: 40, minZ: 0, maxZ: 1, color });
|
||||
setTimeout(() => {
|
||||
loaded = true;
|
||||
}, 100);
|
||||
@ -48,10 +49,10 @@
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 2s;
|
||||
transition: opacity 4s;
|
||||
}
|
||||
|
||||
.loaded {
|
||||
opacity: 0.2;
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
|
BIN
src/content/projects/plantarium/images/plantarium-screenshot.png
(Stored with Git LFS)
Normal file
BIN
src/content/projects/plantarium/images/plantarium-screenshot.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
HostUrl=about:internet
|
@ -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.
|
||||
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
|
||||
|
||||
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_unreal from "./images/screenshot-unreal.jpg"
|
||||
import screenshot_davinci from "./images/screenshot-davinci.jpg"
|
||||
import plantarium_screenshot from "./images/plantarium-screenshot.png"
|
||||
import Plantarium from "./images/plantarium.png"
|
||||
import ImageGallery from "@components/ImageGallery.svelte"
|
||||
|
||||
@ -40,6 +43,7 @@ import ImageGallery from "@components/ImageGallery.svelte"
|
||||
|
||||
<Leaves client:load/>
|
||||
|
||||
|
||||
<ImageSlider title="Erster Prototyp" client:load>
|
||||
<Image src={page01_0} alt="Stem 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
|
||||
|
||||
<Image src={Plantarium} alt="Plantariums uses nodes to create plants"/>
|
||||
|
||||
<ImageSlider title="Beispiele von Node Systemen" client:load>
|
||||
<Image src={screenshot_geometry_nodes} alt="Blenders uses nodes to create geometry"/>
|
||||
<Image src={screenshot_houdini} alt="Houdini uses nodes for vfx/simulations"/>
|
||||
|
9
src/env.d.ts
vendored
9
src/env.d.ts
vendored
@ -1,3 +1,12 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
/// <reference types="unplugin-icons/types" />
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
colors: import("svelte/store").Writable<{
|
||||
background: string;
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
// function to turn css rgb() strings to hex
|
||||
export function rgbToHex(rgb: string) {
|
||||
let hex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
||||
@ -12,3 +14,7 @@ export function rgbToHex(rgb: string) {
|
||||
.join("")
|
||||
);
|
||||
}
|
||||
|
||||
export const colors = writable({
|
||||
background: "#f0f0f0",
|
||||
});
|
||||
|
@ -23,6 +23,7 @@ export const ui = {
|
||||
'nav.videos': 'Videos',
|
||||
'nav.photos': 'Photos',
|
||||
'toc.title': 'Table of Contents',
|
||||
"resume": "Resume",
|
||||
},
|
||||
de: {
|
||||
"en": "English",
|
||||
@ -39,6 +40,7 @@ export const ui = {
|
||||
'nav.projects': 'Projekte',
|
||||
'nav.videos': 'Videos',
|
||||
'nav.photos': 'Fotos',
|
||||
"resume": "Lebenslauf",
|
||||
'toc.title': 'Inhaltsverzeichnis',
|
||||
},
|
||||
} as const;
|
||||
|
@ -74,11 +74,44 @@ import "./global.css";
|
||||
body {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
body > * {
|
||||
main,
|
||||
header,
|
||||
footer {
|
||||
background: var(--background-dark);
|
||||
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) {
|
||||
body > * {
|
||||
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">
|
||||
<Nav />
|
||||
</header>
|
||||
<main id="main-content" class="flex flex-col gap-4">
|
||||
<main id="main-content" class="relative flex flex-col gap-6">
|
||||
<slot />
|
||||
</main>
|
||||
<footer class="px-4 flex gap-8">
|
||||
<footer class="mx-8 mb-4 mt-2 flex gap-8">
|
||||
<LanguagePicker />
|
||||
<a
|
||||
href="https://git.max-richter.dev/max/website"
|
||||
|
Loading…
Reference in New Issue
Block a user