mirror of
https://github.com/bartvdbraak/hellob.art.git
synced 2025-04-27 09:31:21 +00:00
refactor: imagefade component refactored as carousel
This commit is contained in:
parent
fe2a5d00f9
commit
ae62f93735
4 changed files with 68 additions and 37 deletions
57
src/lib/components/site/image-fade-carousel.svelte
Normal file
57
src/lib/components/site/image-fade-carousel.svelte
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
export let images: { src: string; alt: string; style?: string }[] = [];
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
/* global NodeJS */
|
||||||
|
let interval: string | number | NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
|
const start = () => (interval = setInterval(() => (index = (index + 1) % images.length), 8000));
|
||||||
|
const stop = () => clearInterval(interval);
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
start();
|
||||||
|
return () => stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleMarkerClick(i: number) {
|
||||||
|
stop();
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="relative h-[500px]">
|
||||||
|
{#each images as img, i}
|
||||||
|
<enhanced:img
|
||||||
|
src={img.src}
|
||||||
|
alt={img.alt}
|
||||||
|
class:current-img={index === i}
|
||||||
|
class="absolute inset-0 h-full w-full rounded-xl object-cover opacity-0 transition-opacity duration-1000 ease-out {img.style}"
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
<div class="absolute bottom-[5%] left-[50%] grid translate-x-[-50%] grid-flow-col gap-2">
|
||||||
|
{#each images as _, i (_.src)}
|
||||||
|
<button on:click={() => handleMarkerClick(i)}>
|
||||||
|
<svg height="20" width="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="8"
|
||||||
|
class:current-marker={index === i}
|
||||||
|
class="transition-fill fill-gray-500 duration-500 ease-out"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.current-img {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.current-marker {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,33 +0,0 @@
|
||||||
<script>
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import catImg from '$lib/assets/root-cat.jpg?enhanced';
|
|
||||||
import meImg from '$lib/assets/root-me.jpg?enhanced';
|
|
||||||
|
|
||||||
const images = [
|
|
||||||
{ src: meImg, alt: 'Portrait of Bart van der Braak', style: 'object-[50%_10%]' },
|
|
||||||
{ src: catImg, alt: 'Noire yawning cat and a bottle of whiskey with glass', style: '' }
|
|
||||||
];
|
|
||||||
|
|
||||||
let currentIndex = 0;
|
|
||||||
let currentImage = images[currentIndex];
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
currentIndex = (currentIndex + 1) % images.length;
|
|
||||||
currentImage = images[currentIndex];
|
|
||||||
}, 15000);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="relative h-full min-h-96 w-full md:min-h-44">
|
|
||||||
{#each images as image}
|
|
||||||
<enhanced:img
|
|
||||||
src={image.src}
|
|
||||||
alt={image.alt}
|
|
||||||
class="absolute left-0 top-0 h-full w-full rounded-xl object-cover transition-opacity duration-1000 {image.style}"
|
|
||||||
style:opacity={image === currentImage ? 1 : 0}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
|
@ -4,7 +4,7 @@ export { default as SiteNavBar } from './site-navbar.svelte';
|
||||||
export { default as SiteHeader } from './site-header.svelte';
|
export { default as SiteHeader } from './site-header.svelte';
|
||||||
export { default as TailwindIndicator } from './tailwind-indicator.svelte';
|
export { default as TailwindIndicator } from './tailwind-indicator.svelte';
|
||||||
export { default as ModeToggle } from './mode-toggle.svelte';
|
export { default as ModeToggle } from './mode-toggle.svelte';
|
||||||
export { default as ImageFade } from './image-fade.svelte';
|
export { default as ImageFadeCarousel } from './image-fade-carousel.svelte';
|
||||||
export { default as OgImage } from './opengraph-image.svelte';
|
export { default as OgImage } from './opengraph-image.svelte';
|
||||||
|
|
||||||
export * from './icons';
|
export * from './icons';
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { Icons, ImageFade } from '$lib/components/site';
|
import { Icons, ImageFadeCarousel, SiteHeader } from '$lib/components/site';
|
||||||
import { SiteHeader } from '$lib/components/site';
|
|
||||||
import { buttonVariants } from '$lib/components/ui/button';
|
import { buttonVariants } from '$lib/components/ui/button';
|
||||||
import { siteConfig } from '$lib/config/site';
|
import { siteConfig } from '$lib/config/site';
|
||||||
import { cn } from '$lib/utils';
|
import { cn } from '$lib/utils';
|
||||||
|
|
||||||
|
import catImg from '$lib/assets/root-cat.jpg?enhanced';
|
||||||
|
import meImg from '$lib/assets/root-me.jpg?enhanced';
|
||||||
|
|
||||||
|
const images = [
|
||||||
|
{ src: meImg, alt: 'Portrait of Bart van der Braak', style: 'object-[50%_10%]' },
|
||||||
|
{ src: catImg, alt: 'Noire yawning cat and a bottle of whiskey with glass', style: '' }
|
||||||
|
];
|
||||||
|
|
||||||
$: title = $page.data.title;
|
$: title = $page.data.title;
|
||||||
$: subTitle = $page.data.subTitle;
|
$: subTitle = $page.data.subTitle;
|
||||||
</script>
|
</script>
|
||||||
|
@ -71,7 +78,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<ImageFade />
|
<ImageFadeCarousel {images} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue