Compare commits

...
Author SHA1 Message Date
Brandon Thomas 97a2028c0d swap out the background 2025-05-19 23:00:51 -04:00
3 changed files with 22 additions and 157 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

@@ -0,0 +1,19 @@
.tile-background-animation {
background-image: url('/resources/images/tilebg.png');
background-repeat: repeat;
background-size: 512px;
animation: background-animation-scrolling 60s linear infinite;
-webkit-animation: background-animation-scrolling 60s linear infinite;
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
}
@keyframes background-animation-scrolling {
0% {
background-position: 0 0;
}
100% {
background-position: 512px 512px;
}
}
@@ -1,168 +1,14 @@
import { useEffect, useState, useRef } from "react";
function getRandomImages(count: number) {
const images = Array.from({ length: count }, (_, i) => ({
id: i + 1,
src: `/resources/images/generate/image${i + 1}.png`,
alt: `Generated image ${i + 1}`,
}));
// Shuffle the array
return [...images].sort(() => Math.random() - 0.5);
}
interface ImageColumnProps {
images: Array<{ id: number; src: string; alt: string }>;
delay: number;
reverse?: boolean;
isLoaded: boolean;
duration?: number;
}
function ImageColumn({
images,
delay,
reverse = false,
duration = 100,
isLoaded,
}: ImageColumnProps) {
const columnRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!columnRef.current) return;
const column = columnRef.current;
const animation = column.animate(
[
{ transform: reverse ? "translateY(-50%)" : "translateY(0)" },
{ transform: reverse ? "translateY(0)" : "translateY(-50%)" },
],
{
duration: duration * 1000,
iterations: Infinity,
easing: "linear",
delay: delay + 1000,
fill: "both",
},
);
if (!isLoaded) {
animation.pause();
}
return () => {
animation.cancel();
};
}, [delay, duration, isLoaded, reverse]);
return (
<div className="relative h-screen overflow-hidden">
<div
ref={columnRef}
className="absolute left-0 right-0 flex flex-col gap-6"
style={{
transform: reverse ? "translateY(-50%)" : "translateY(0)",
willChange: "transform",
}}
>
{[...images, ...images].map((image, i) => (
<div
key={`${image.id}-${i}`}
className={`relative aspect-[4/5] w-full overflow-hidden rounded-lg shadow-lg transition-all duration-700 ease-out ${
isLoaded
? "translate-y-0 opacity-100"
: "translate-y-12 opacity-0"
}`}
style={{
transitionDelay: `${delay + (i % images.length) * 50}ms`,
}}
>
<img
src={image.src}
alt={image.alt}
className="h-full w-full object-cover"
loading="lazy"
/>
</div>
))}
</div>
</div>
);
}
import "./Background.css";
export default function GalleryBackground() {
const [images, _setImages] = useState(() => getRandomImages(20));
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
// delay for smooth animation
const timer = setTimeout(() => {
setIsLoaded(true);
}, 100);
return () => clearTimeout(timer);
}, []);
// Columns for masonry layout
const columns = {
col1: images.filter((_, i) => i % 5 === 0),
col2: images.filter((_, i) => i % 5 === 1),
col3: images.filter((_, i) => i % 5 === 2),
col4: images.filter((_, i) => i % 5 === 3),
col5: images.filter((_, i) => i % 5 === 4),
};
return (
<>
<div className="pointer-events-none fixed inset-0 z-[1] overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,rgba(0,0,0,0.00)_49%,rgba(0,0,0,0.60)_100%)]" />
<div className="fixed inset-0 z-0 overflow-hidden">
<div className="fixed inset-0 z-0 overflow-hidden tile-background-animation">
<div
className={`h-full w-full transition-opacity duration-1000 ${isLoaded ? "opacity-30" : "opacity-0"}`}
className={`h-full w-full transition-opacity duration-1000 opacity-30`}
>
<div className="absolute inset-0 grid grid-cols-5 gap-6 px-6 opacity-35">
<ImageColumn
images={columns.col1}
delay={0}
isLoaded={isLoaded}
duration={100}
/>
<ImageColumn
images={columns.col2}
delay={columns.col1.length * 50}
isLoaded={isLoaded}
reverse={true}
duration={100}
/>
<ImageColumn
images={columns.col3}
delay={(columns.col1.length + columns.col2.length) * 50}
isLoaded={isLoaded}
duration={125}
/>
<ImageColumn
images={columns.col4}
delay={
(columns.col1.length +
columns.col2.length +
columns.col3.length) *
50
}
isLoaded={isLoaded}
reverse={true}
duration={160}
/>
<ImageColumn
images={columns.col5}
delay={
(columns.col1.length +
columns.col2.length +
columns.col3.length +
columns.col4.length) *
50
}
isLoaded={isLoaded}
duration={110}
/>
</div>
</div>
</div>