This commit is contained in:
Christofer 2023-09-15 20:46:48 +04:00
parent e617e175b5
commit a94b30e176
14 changed files with 50 additions and 250 deletions

3
.vscode/extensions.json vendored Executable file
View file

@ -0,0 +1,3 @@
{
"recommendations": ["bradlc.vscode-tailwindcss", "svelte.svelte-vscode"]
}

View file

@ -1,27 +0,0 @@
import { generate } from 'critical'
generate({
inline: true,
base: 'build/',
src: 'index.html',
target: 'index-critical.html',
width: 1300,
height: 900
})
// generate({
// inline: true,
// base: 'build/',
// src: 'index.html',
// target: 'index.c.html',
// dimensions: [
// {
// width: 1200,
// height: 900
// },
// {
// width: 480,
// height: 900
// }
// ]
// })

View file

@ -1,22 +0,0 @@
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$parent_path"
find "../static/imgs/profile_pictures/" -type f \
\( -iname "*.jpg" -o -iname "*.png" -o -iname "*.gif" -o -iname "*.bmp" -o -iname "*.jpeg" -o -iname "*.webp" \) -not -name "generated_*" -print0 |
while IFS= read -r -d '' filepath; do
echo "$filepath" gets blurred
directory=$(dirname "$filepath")
filename=$(basename "$filepath")
for SIZE in 100x100 64x64 48x48 32x32
do
generated_filename="${directory}/generated_${SIZE}-${filename}"
magick "$filepath" --resize "${SIZE}" "${generated_filename}"
done
done

View file

@ -96,6 +96,7 @@ export function getBlurredPath(path) {
return `${path.substring(0, path.lastIndexOf('/'))}/generated_${path.split('/').at(-1)}`
}
/** Get a random item from an array */
export function getRandom(array) {
return array.at(Math.floor(Math.random() * array.length))
}

View file

@ -9,5 +9,29 @@ Lt. Dixon Piper:
That's really f***ed up.
MacGruber:
Thanks.`
Thanks.`,
`MacGruber:
Looks like you're keeping your bod pretty tight.
Frank Korver:
You're looking pretty good yourself.
MacGruber:
Well, everday's a workout when you gotta carry around a 20 pound python in your jeans.
Frank Korver:
You and your dick comments.
MacGruber:
It's fun to say them.
Frank Korver:
It's fun to hear them.
MacGruber:
That's why I say them.
Frank Korver:
And that's why I listen.`
]

View file

@ -6,10 +6,11 @@
import '@fontsource-variable/work-sans'
import '@fontsource/ibm-plex-mono/500.css'
import { quotes } from '$lib/components/Quotes'
import { getRandom } from '$lib/Helper.mjs'
onMount(() => {
if (import.meta.env.PROD) {
console.log(quotes.at(Math.floor(Math.random() * quotes.length)))
console.log(getRandom(quotes))
}
})
</script>

View file

@ -162,7 +162,8 @@
image: '/imgs/profile_pictures/jacekpoz.svg',
coordinates: [180, 730],
size: 80,
class: 'outline-yellow-500 bg-orange-700'
class: 'outline-yellow-500 bg-orange-700',
quote: '"Piss blob"'
}
]

View file

@ -76,7 +76,7 @@
}
onMount(() => {
// Nesecarry as the load image load event might not get fired when its already loaded
// Nesecarry as the load image event might not get fired when its already loaded ( for example after a page reload )
hasImageLoaded = hasImageLoaded || imageElement.complete
})

View file

@ -10,7 +10,7 @@
/** @type {string | undefined} */
export let containerClass = undefined
/** @type {string}
* The path to the image. Usually the file within `static`, but can also be an URL
* The path to the image. Usually the file within `static`, but can also be an URL. Defaults to `generated_<image>`
*/
export let blurredBackground = undefined
</script>

View file

@ -1,106 +0,0 @@
<script>
import { onMount } from 'svelte'
import { createNoise2D } from 'simplex-noise'
import { match } from 'ts-pattern'
import clsx from 'clsx'
import { getIsMobile } from '$lib/Helper.mjs'
// Currently this is unused. I left it in here, in case it would be useful in the future
const maxSize = 24
const minSize = 7
const size = Math.max(Math.random() * maxSize, minSize)
/** How much the fireflies can vanish into the edges of the screen. Include their invisible padding for mouse detection. */
const edgeClip = maxSize * 8
const noiseY = createNoise2D()
const noiseX = createNoise2D()
const SPEED = Math.random() * 5 + 2
let classes = clsx(size > maxSize / 2 ? 'bg-primary/70' : 'bg-blue-500/70')
let x = 0
let y = 0
onMount(() => {
x = window.innerWidth / (Math.random() * 4) - maxSize * 6
y = window.innerHeight / (Math.random() * 4) + 100
// The animation is way too heavy for mobile
if (getIsMobile()) return
let animationId
let i = 0
animate()
return () => cancelAnimationFrame(animationId)
async function animate() {
x += match(x)
.when(
(x_) => x_ > window.innerWidth + edgeClip,
() => -10
)
.when(
(x) => x < -edgeClip,
() => 10
)
.otherwise(() => noiseX(i, 1) * SPEED)
y += match(y)
.when(
(y) => y > window.innerHeight + edgeClip,
() => -10
)
.when(
(y) => y < -edgeClip,
() => 10
)
.otherwise(() => noiseY(i, 1) * SPEED)
i += 0.005
animationId = requestAnimationFrame(animate)
}
})
</script>
<div
class="firefly pointer-events-auto absolute left-0 top-0 z-0 hidden p-24 opacity-50 transition-opacity hover:opacity-100 max-sm:[contain:strict] md:block"
style:--x={x + 'px'}
style:--y={y + 'px'}
style="--size:{size}px; --fadeDelay: {Math.random() * 6 - 3}s"
>
<div class={clsx('firefly-inner', classes)} />
</div>
<style lang="postcss">
.firefly {
/* transform: translate3d(50px, calc(var(--x) * 200px), 0px); */
transform: translate3d(var(--x, 5), var(--y, 2), 0px);
contain: strict;
}
.firefly-inner {
min-height: var(--size);
min-width: var(--size);
border-radius: 50%;
contain: layout size style;
box-shadow:
0px 0px 25px theme(colors.emerald.400),
0px 0px 12px theme(colors.sky.400);
animation: fade 3s ease-in-out infinite alternate;
animation-delay: var(--fadeDelay);
}
@keyframes fade {
0%,
40%,
66% {
opacity: 0%;
}
99%,
20% {
opacity: 100%;
}
}
</style>

View file

@ -30,6 +30,7 @@
const MIN_LIFESPAN_TILE = 800
const MAX_TILES_PER_CLICK = 15
const MIN_TILES_PER_CLICK = 2
/** How fast the user has to click to progress */
const CLICK_EACH_MS = 400
const ASCENION_FALLOFF = -ASCENION_CLICKS / 20
@ -40,8 +41,10 @@
switchMap((value) =>
merge(
of(value),
/** If no new value comes in, start decreasing the progress */
interval(CLICK_EACH_MS + 100).pipe(
take(ASCENION_CLICKS),
take(ASCENION_CLICKS), // Prevent this interval from running forever
map(() => ASCENION_FALLOFF)
)
)
@ -49,10 +52,12 @@
scan((level, value) => Math.min(ASCENION_CLICKS, Math.max(level + value, 0))),
startWith(0)
)
/** How many clicks are left in percent */
const relativeLevel$ = clickLevel$.pipe(map((clicks) => clicks / ASCENION_CLICKS))
const cubibRelativeLevel$ = relativeLevel$.pipe(map(cubicInOut))
/** Tween/Ease the percents for a nicer look */
const cubicRelativeLevel$ = relativeLevel$.pipe(map(cubicInOut))
const expoRelativeLevel$ = relativeLevel$.pipe(map(expoInOut))
// const hasAscended$ = of(true)
const hasAscended$ = relativeLevel$.pipe(
filter((level) => level >= 1),
first(),
@ -64,7 +69,8 @@
const tiles$ = click$.pipe(
switchMap(() =>
merge(
of(Math.floor(lerp(MIN_TILES_PER_CLICK, MAX_TILES_PER_CLICK, $cubibRelativeLevel$))),
of(Math.floor(lerp(MIN_TILES_PER_CLICK, MAX_TILES_PER_CLICK, $cubicRelativeLevel$))),
// Remove the tiles after a timeout, if no new ones came in
timer(MAX_LIFESPAN_TILE)
)
),
@ -75,9 +81,9 @@
startWith([])
)
$: hue = lerp(200, 130, $cubibRelativeLevel$)
$: scale = lerp(0.9, 2, $cubibRelativeLevel$)
$: translateY = lerp(0, 10, $cubibRelativeLevel$)
$: hue = lerp(200, 130, $cubicRelativeLevel$)
$: scale = lerp(0.9, 2, $cubicRelativeLevel$)
$: translateY = lerp(0, 10, $cubicRelativeLevel$)
/** @type {HTMLDivElement} */
let containerElement
@ -109,7 +115,7 @@
<div class="pointer-events-none absolute left-1/2 top-1/2 -z-10">
{#each $tiles$ as _}
<GitTile
lifeSpan={lerp(MIN_LIFESPAN_TILE, MAX_LIFESPAN_TILE, $cubibRelativeLevel$)}
lifeSpan={lerp(MIN_LIFESPAN_TILE, MAX_LIFESPAN_TILE, $cubicRelativeLevel$)}
maxSpeed={lerp(10, 38, $expoRelativeLevel$)}
minSpeed={lerp(1, 9, $expoRelativeLevel$)}
/>

View file

@ -13,8 +13,6 @@
function toggleExpanded() {
isExpanded = !isExpanded
}
//! TODO close mobile menu on navigation
</script>
<header

View file

@ -1,80 +0,0 @@
<script>
const circlesAmount = 10
/** In millisseconds */
const animationDuration = 8000
const circles = Array.from({ length: circlesAmount }, () => 1)
/**
*
* @param node {HTMLElement}
* @param param1
*/
function animateElement(node, { delay, index, amount }) {
const delayFrames = Array.from({ length: index }).map(() => ({
scale: 0
}))
node.animate([{ scale: CSS.number(0) }, { scale: CSS.number(3), opacity: 0 }], {
iterations: Infinity,
duration: animationDuration,
delay: animationDuration / (amount - index + 1) + animationDuration / (amount - index + 1),
easing: 'cubic-bezier(1, 0.1 , 0.9, 1)',
fill: 'backwards'
})
}
</script>
<div class="wrapper">
{#each circles as _, index}
<div
class="circle"
style:--percent={((index + 1) / circles.length) * 100 + '%'}
style:--index={index}
style:--amount={circles.length}
/>
{/each}
<!-- use:animateElement={{ index, amount: circles.length }} -->
</div>
<style lang="postcss">
.wrapper {
position: absolute;
top: 40px;
right: 40px;
width: 400px;
aspect-ratio: 1;
filter: drop-shadow(0 0 44px blue);
/* background: red; */
}
.circle {
position: absolute;
inset: 0;
height: 100%;
width: 100%;
opacity: 0.05;
background: radial-gradient(
closest-side,
transparent,
color-mix(in hsl, theme(colors.blue.500), theme(colors.pink.500) var(--percent)),
transparent 90%
);
transition: all 2200ms;
.wrapper:hover & {
opacity: 1;
transition: all 1200ms ease-in;
}
animation: loop infinite backwards;
}
@keyframes loop {
from {
scale: 0;
}
to {
scale: 1;
}
}
</style>

View file

@ -12,6 +12,7 @@
let enabled = false
function setEnabled({ detail }) {
// Show the effect when the user scrolls in and keep it enabled until the user scrolls up from it again
const { inView, scrollDirection } = detail
const isScrollingUp = scrollDirection.vertical === 'up'