156 lines
5.6 KiB
TypeScript
156 lines
5.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
|
|
const backgroundImages = [
|
|
"/background/Autumn birger-strahl-6YZgnYaPD5s-unsplash.jpeg",
|
|
"/background/Moneral tobias-reich-VltYe88rkt8-unsplash.jpeg",
|
|
"/background/aaron-burden-cGW1w-qLix8-unsplash.jpg",
|
|
"/background/aaron-burden-xtIYGB0KEqc-unsplash.jpg",
|
|
"/background/art credit library-of-congress-ULl31hxiehE-unsplash.jpeg",
|
|
"/background/art-institute-of-chicago-fayEVJ03T7M-unsplash.jpg",
|
|
"/background/art-institute-of-chicago-j-3IgXK3iJg-unsplash.jpg",
|
|
"/background/art-institute-of-chicago-ueWnHtoaplI-unsplash.jpg",
|
|
"/background/art-institute-of-chicago-yIgLfU6EEBw-unsplash.jpg",
|
|
"/background/birmingham-museums-trust-M9ryRhN4YSI-unsplash.jpg",
|
|
"/background/david-ramirez-LC7lLC9jDzw-unsplash.jpg",
|
|
"/background/europeana-HDIOpM_XXbI-unsplash.jpg",
|
|
"/background/gabor-juhasz-B1Zyw7sdm5w-unsplash.jpg",
|
|
"/background/gonzalo-mendiola-XXCrAQgQnVw-unsplash.jpg",
|
|
"/background/ian-keefe-OgcJIKRnRC8-unsplash.jpg",
|
|
"/background/japan credit dale-scogings-_SBsVi4kmkY-unsplash.jpeg",
|
|
"/background/japan credit david-edelstein-N4DbvTUDikw-unsplash.jpeg",
|
|
"/background/japan credit falco-negenman-K8MMfFifWcE-unsplash.jpeg",
|
|
"/background/japan credit galen-crout-0_xMuEbpFAQ-unsplash.jpeg",
|
|
"/background/japan credit gilly-cLnFkSji734-unsplash.jpeg",
|
|
"/background/japan credit matthew-buchanan-VVi59Xtsd8Y-unsplash.jpeg",
|
|
"/background/japan credit redd-f-Bxzrd0p6yOM-unsplash.jpeg",
|
|
"/background/japan credit redd-f-wPMvPMD9KBI-unsplash.jpeg",
|
|
"/background/japan credit sorasak-_UIN-pFfJ7c-unsplash.jpeg",
|
|
"/background/japan credittianshu-liu-SBK40fdKbAg-unsplash.jpeg",
|
|
"/background/japan.jpeg",
|
|
"/background/joel-holland-TRhGEGdw-YY-unsplash.jpg",
|
|
"/background/marko-blazevic-S7mAngnWV1A-unsplash.jpg",
|
|
"/background/museum-of-new-zealand-te-papa-tongarewa-h2qlQSm7N-0-unsplash.jpg",
|
|
"/background/redd-f-Lm5rkxzgiFQ-unsplash.jpg",
|
|
"/background/spencer-davis-ONVA6s03hg8-unsplash.jpg",
|
|
"/background/summer credit spencer-everett-DdVOCPTofFc-unsplash.jpeg",
|
|
"/background/summer.jpeg",
|
|
"/background/sylvain-mauroux-jYCUBAIUsk8-unsplash.jpg",
|
|
"/background/the-cleveland-museum-of-art-6uIO1CNv3Vc-unsplash.jpg",
|
|
"/background/the-cleveland-museum-of-art-Tl9uudd4DOE-unsplash.jpg",
|
|
"/background/the-cleveland-museum-of-art-WQOzF8TSnRQ-unsplash.jpg",
|
|
"/background/tingfeng-xia-WwKrhith4l4-unsplash.jpg",
|
|
"/background/vegetal credit yuya-murakami-VkcD1QxtY4A-unsplash.jpeg",
|
|
"/background/vegetal ryunosuke-kikuno-U8_eaHSUwdw-unsplash.jpeg"
|
|
];
|
|
|
|
export function useBackgroundImage() {
|
|
const [currentBackground, setCurrentBackground] = useState(backgroundImages[0]);
|
|
|
|
const changeBackground = () => {
|
|
const currentIndex = backgroundImages.indexOf(currentBackground);
|
|
const nextIndex = (currentIndex + 1) % backgroundImages.length;
|
|
setCurrentBackground(backgroundImages[nextIndex]);
|
|
};
|
|
|
|
useEffect(() => {
|
|
// Set initial random background
|
|
const randomIndex = Math.floor(Math.random() * backgroundImages.length);
|
|
setCurrentBackground(backgroundImages[randomIndex]);
|
|
}, []);
|
|
|
|
return { currentBackground, changeBackground };
|
|
}
|
|
|
|
export function BackgroundSwitcher({ children }: { children: React.ReactNode }) {
|
|
const [background, setBackground] = useState("");
|
|
const [imageError, setImageError] = useState(false);
|
|
|
|
// Function to preload an image
|
|
const preloadImage = (src: string): Promise<string> => {
|
|
return new Promise((resolve, reject) => {
|
|
const img = new Image();
|
|
img.src = src;
|
|
img.onload = () => resolve(src);
|
|
img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
|
|
});
|
|
};
|
|
|
|
const getRandomBackground = async () => {
|
|
let attempts = 0;
|
|
const maxAttempts = backgroundImages.length;
|
|
|
|
while (attempts < maxAttempts) {
|
|
try {
|
|
const randomIndex = Math.floor(Math.random() * backgroundImages.length);
|
|
const newBackground = backgroundImages[randomIndex];
|
|
|
|
if (newBackground !== background) {
|
|
// Try to preload the image
|
|
await preloadImage(newBackground);
|
|
console.log("Successfully loaded:", newBackground);
|
|
return newBackground;
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to load image:", error);
|
|
}
|
|
attempts++;
|
|
}
|
|
|
|
// If all attempts fail, return the first image as fallback
|
|
return backgroundImages[0];
|
|
};
|
|
|
|
useEffect(() => {
|
|
const initBackground = async () => {
|
|
try {
|
|
const newBg = await getRandomBackground();
|
|
setBackground(newBg);
|
|
setImageError(false);
|
|
} catch (error) {
|
|
console.error("Error setting initial background:", error);
|
|
setImageError(true);
|
|
}
|
|
};
|
|
|
|
initBackground();
|
|
}, []);
|
|
|
|
const handleClick = async (e: React.MouseEvent) => {
|
|
if (e.target === e.currentTarget) {
|
|
try {
|
|
const newBg = await getRandomBackground();
|
|
console.log("Changing background to:", newBg);
|
|
setBackground(newBg);
|
|
setImageError(false);
|
|
} catch (error) {
|
|
console.error("Error changing background:", error);
|
|
setImageError(true);
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="min-h-screen relative"
|
|
onClick={handleClick}
|
|
>
|
|
{/* Background Image */}
|
|
<div
|
|
className="fixed inset-0 z-0 transition-opacity duration-500"
|
|
style={{
|
|
backgroundImage: `url(${background})`,
|
|
backgroundSize: 'cover',
|
|
backgroundPosition: 'center',
|
|
opacity: imageError ? 0 : 0.3
|
|
}}
|
|
/>
|
|
|
|
{/* Content */}
|
|
<div className="relative z-10">
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|