Moving between images works, and we preload one on either side of the current index. There's also the beginnings of some slide animations which is my next job.ご主人様
parent
c471107b73
commit
cfc51f04c3
@ -1,5 +1,39 @@
|
||||
<script>
|
||||
let world = 'qt';
|
||||
import { onMount } from 'svelte';
|
||||
import Lightbox from './lightbox.svelte';
|
||||
let file_list;
|
||||
let open;
|
||||
let thumb_list = [];
|
||||
|
||||
const url = {
|
||||
root: 'https://wg.flanchan.moe/cake/',
|
||||
thumb: 'thumb/',
|
||||
files: 'filelist.txt'
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
file_list = await fetch(url.root + url.files)
|
||||
.then(resp => resp.text())
|
||||
.then(data => data.split('\n'));
|
||||
|
||||
// Loop backwards efficiently
|
||||
for (let i = file_list.length - 2; i >= 0; i--) {
|
||||
const file = file_list[i];
|
||||
thumb_list.push(file.substr(0, file.lastIndexOf('.')) + '.jpg');
|
||||
}
|
||||
});
|
||||
|
||||
function open_lightbox(i) {
|
||||
open = null;
|
||||
open = i;
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1 class="text-center text-4xl font-bold">Hey {world}</h1>
|
||||
{#if file_list}
|
||||
<section>
|
||||
{#each thumb_list as thumb, i}
|
||||
<img on:click={() => open_lightbox(i)} src="{url.root}{url.thumb}{thumb}" />
|
||||
{/each}
|
||||
</section>
|
||||
{/if}
|
||||
<Lightbox open={open} url={url} images={file_list} />
|
||||
|
@ -0,0 +1,108 @@
|
||||
<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>
|
Loading…
Reference in new issue