You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wirecake/src/lightbox.svelte

109 lines
2.0 KiB

<script>
import { onMount } from 'svelte';
export let open;
export let url;
export let images;
let slide_classes = '';
let class_list = 'lightbox';
let should_open = true;
$: image = open !== null && open >= 0 ? set_images() : '';
$: is_open(open);
function is_open(i) {
if (should_open && i !== null && i >= 0) {
class_list += ' open'
should_open = false;
}
}
function close(e) {
if (e.target.tagName === 'IMG')
return;
if (!should_open) {
open = null;
should_open = true;
class_list = 'lightbox';
slide_classes = '';
}
}
function set_images() {
const img = images.length - (open + 2)
return [
url.root + images[img - 1],
url.root + images[img],
url.root + images[img + 1]
]
}
function handle_keys(e) {
if(should_open)
return;
switch(e.key) {
case 'ArrowRight':
open = open === (images.length - 2) ? 0 : open + 1;
break;
case 'ArrowLeft':
open = open === 0 ? images.length - 2 : open - 1;
slide_classes = 'slide-in-left';
break;
}
}
onMount(() => {
let lightbox = document.getElementById('lightbox');
lightbox.addEventListener('animationend', () => slide_classes = '');
});
</script>
<style>
.slide-in-left {
animation: slide-in-left .3s ease;
}
@keyframes slide-in-left {
from {
opacity: 0;
transform: translate3d(-60%, 0, 0);
}
to {
visibility: visible;
transform: translate3d( 0, 0, 0);
opacity: 1;
}
}
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
opacity: 1;
transition: opacity 1s;
display: flex;
justify-content: center;
align-items: center;
z-index: -1;
}
.open {
background-color: rgba(0,0,0,0.7);
z-index: 0;
}
</style>
<svelte:window on:keydown={handle_keys} />
<div id="lightbox" class="{class_list} {slide_classes}" on:click={close}>
<img class=" hidden" rel="preload" src="{image[0]}" />
<img class="object-contain max-w-full max-h-full" src="{image[1]}" />
<img class="hidden" rel="preload" src="{image[2]}" />
</div>