2025-02-15 23:08:31 +00:00
|
|
|
---
|
|
|
|
import { Image } from "astro:assets";
|
2025-03-13 21:45:16 +00:00
|
|
|
import type { CollectionEntry } from "astro:content";
|
2025-02-15 23:08:31 +00:00
|
|
|
|
|
|
|
interface Props {
|
2025-03-13 21:45:16 +00:00
|
|
|
images: CollectionEntry<"projects">[];
|
2025-04-26 16:20:40 +01:00
|
|
|
interval?: number;
|
2025-02-15 23:08:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const { interval = 3000, images } = Astro.props;
|
|
|
|
---
|
|
|
|
|
|
|
|
<div
|
2025-02-25 13:17:10 +00:00
|
|
|
class="group relative min-h-[50svh] w-full overflow-hidden"
|
2025-02-15 23:08:31 +00:00
|
|
|
data-interval={interval}
|
|
|
|
>
|
|
|
|
{
|
|
|
|
images.map((image: any, index: number) => (
|
|
|
|
<div
|
|
|
|
class="absolute top-0 left-0 h-full w-full transition-opacity duration-500"
|
|
|
|
style={`opacity: ${index === 0 ? 1 : 0}; z-index: ${
|
|
|
|
index === 0 ? 10 : 1
|
|
|
|
}`}
|
|
|
|
data-slide-index={index}
|
|
|
|
>
|
|
|
|
<a href={`/${image.collection}/${image.slug}`}>
|
|
|
|
<Image
|
|
|
|
src={image.data.image.url}
|
|
|
|
alt={`Slide ${index + 1}`}
|
2025-02-25 13:17:10 +00:00
|
|
|
class="h-full w-full rounded-sm object-cover transition-all duration-300 group-hover:brightness-50"
|
2025-02-15 23:08:31 +00:00
|
|
|
loading="eager"
|
2025-06-20 10:56:34 +01:00
|
|
|
{...(index === 0 && { priority: true })}
|
2025-02-15 23:08:31 +00:00
|
|
|
/>
|
2025-07-25 19:15:46 +01:00
|
|
|
<div class="relative opacity-100 transition-all delay-100 duration-300 ease-in-out group-hover:opacity-100 md:opacity-0">
|
|
|
|
<p class="bg-primary/50 absolute right-5 bottom-5 rounded-sm px-1 py-0.5 font-medium text-white md:bg-transparent">
|
2025-04-26 16:20:40 +01:00
|
|
|
{image.data.title}
|
|
|
|
</p>
|
|
|
|
</div>
|
2025-02-15 23:08:31 +00:00
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
))
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<script>
|
2025-07-18 23:29:03 +01:00
|
|
|
const images = Array.from(
|
|
|
|
document.querySelectorAll<HTMLElement>("[data-slide-index]"),
|
|
|
|
);
|
2025-02-15 23:08:31 +00:00
|
|
|
let currentImageIndex = 0;
|
2025-07-18 23:29:03 +01:00
|
|
|
|
|
|
|
const closestRelativeElement = document
|
|
|
|
.querySelector<HTMLElement>("[data-slide-index]")
|
|
|
|
?.closest(".relative") as HTMLElement | null;
|
|
|
|
|
|
|
|
const interval = Number(closestRelativeElement?.dataset?.interval) || 3000;
|
|
|
|
|
|
|
|
for (let i = images.length - 1; i > 0; i--) {
|
|
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
|
|
[images[i], images[j]] = [images[j], images[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
images.forEach((img, index) => {
|
|
|
|
img.style.opacity = index === 0 ? "1" : "0";
|
|
|
|
img.style.zIndex = index === 0 ? "10" : "1";
|
|
|
|
});
|
2025-02-15 23:08:31 +00:00
|
|
|
|
|
|
|
function showNextImage() {
|
|
|
|
images[currentImageIndex].style.opacity = "0";
|
|
|
|
images[currentImageIndex].style.zIndex = "1";
|
2025-07-18 23:29:03 +01:00
|
|
|
|
2025-02-15 23:08:31 +00:00
|
|
|
currentImageIndex = (currentImageIndex + 1) % images.length;
|
2025-07-18 23:29:03 +01:00
|
|
|
|
2025-02-15 23:08:31 +00:00
|
|
|
images[currentImageIndex].style.opacity = "1";
|
|
|
|
images[currentImageIndex].style.zIndex = "10";
|
|
|
|
}
|
|
|
|
|
|
|
|
setInterval(showNextImage, interval);
|
|
|
|
</script>
|