Add style for photos
This commit is contained in:
@ -1,39 +1,31 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getFileName } from '$lib/util/links';
|
|
||||||
import { strf } from '$lib/data/language.js';
|
|
||||||
import Photo from './Photo.svelte';
|
import Photo from './Photo.svelte';
|
||||||
|
|
||||||
/** @type {Item[]} */
|
/** @type {Album} */
|
||||||
export let items = [];
|
export let album;
|
||||||
|
|
||||||
|
/** @type {Item[]?} */
|
||||||
|
export let items = null;
|
||||||
|
|
||||||
export let base = '';
|
export let base = '';
|
||||||
|
|
||||||
export let layout = 'grid';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="gallery"
|
<section>
|
||||||
class:gallery--grid={layout === 'grid'}>
|
|
||||||
{#if layout === 'grid'}
|
|
||||||
<ul>
|
<ul>
|
||||||
{#each items as item (item.item)}
|
{#each (items || album.items) as item (item.item)}
|
||||||
<!-- <Photo src={`${uriBase}&item=${item.item}`} alt={$strf(item.title)} /> -->
|
<Photo src={`${base}${item.item}`} {album} {item} />
|
||||||
<li>
|
|
||||||
<h3>{item.item}</h3>
|
|
||||||
<p>
|
|
||||||
<b>Title:</b> {#if item.title}{$strf(item.title)}{:else}<i>no title</i>{/if}<br />
|
|
||||||
<b>Description:</b> {#if item.description}{$strf(item.description)}{:else}<i>no description</i>{/if}<br />
|
|
||||||
<b>Links:</b> <a href={`${base}${item.item}`}>Open</a> • <a href={`${base}${item.item}/download`}>Download</a><br />
|
|
||||||
<b>Thumbnails:</b> <a href={`${base}${item.item}/t/s`}>Small</a> • <a href={`${base}${item.item}/t/m`}>Medium</a> • <a href={`${base}${item.item}/t/l`}>Large</a> • <a href={`${base}${item.item}/t/full`}>Full</a>
|
|
||||||
</p>
|
|
||||||
<Photo src={`${base}${item.item}`} alt={(item.title ? $strf(item.title) : null) || (item.description ? $strf(item.description) : null) || getFileName(item.item)} />
|
|
||||||
</li>
|
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
{:else}
|
|
||||||
<i>layout not available</i>
|
|
||||||
{/if}
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
list-style: none;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<section class="title">
|
<section class="title">
|
||||||
{#if back}
|
{#if back}
|
||||||
<a href={back}>
|
<a href={back}>
|
||||||
<Icon name="arrow-left" />
|
<Icon mdi="arrow-left" />
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
|
|||||||
@ -1,10 +1,33 @@
|
|||||||
<script>
|
<script>
|
||||||
export let name = '';
|
export let clazz = '';
|
||||||
name;
|
export { clazz as class };
|
||||||
|
export let color = 'currentColor';
|
||||||
|
|
||||||
|
/** @type {string} */
|
||||||
|
export let mdi;
|
||||||
|
|
||||||
|
/** @type {number | string} */
|
||||||
|
export let size = 1;
|
||||||
|
|
||||||
|
let mdiOld = '';
|
||||||
|
let path = '';
|
||||||
|
|
||||||
|
$: {
|
||||||
|
loadIcon(mdi);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: width = size ? (typeof size === 'number' || !Number.isNaN(Number(size)) ? `${size}em` : size) : '1em';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} mdi
|
||||||
|
*/
|
||||||
|
async function loadIcon(mdi) {
|
||||||
|
if (mdi === mdiOld) return;
|
||||||
|
path = (await import(`$lib/icons/${mdi}.js`)).default;
|
||||||
|
//path = icon.path;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svg class={clazz} viewBox="0 0 24 24" style="width: {width}; height: {width}">
|
||||||
|
<path fill={color} d={path} />
|
||||||
<style>
|
</svg>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -1,21 +1,28 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { strf } from "$lib/data/language";
|
||||||
|
import { getFileName } from "$lib/util/links";
|
||||||
|
import Icon from "./Icon.svelte";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source of the image.
|
* The source of the image.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
export let src;
|
export let src;
|
||||||
|
|
||||||
|
/** @type {Album} */
|
||||||
|
export let album;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternative text for the image. Used for accessibility.
|
* The item.
|
||||||
* @type {string | undefined}
|
* @type {Item}
|
||||||
*/
|
*/
|
||||||
export let alt = undefined;
|
export let item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the image is the first one in the viewport.
|
* Whether the image is the first one in the viewport.
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
export let firstViewport = false;
|
export let lazy = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The click handler for the image.
|
* The click handler for the image.
|
||||||
@ -23,18 +30,120 @@
|
|||||||
*/
|
*/
|
||||||
async function clickHandler(event) {
|
async function clickHandler(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
console.log('click', event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The right click handler for the image.
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
async function rightClickHandler(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
console.log('right click', event);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: filename = getFileName(item.item);
|
||||||
|
$: alt = (item.title ? $strf(item.title) : null) || (item.description ? $strf(item.description) : null) || filename;
|
||||||
|
$: title = item.title ? $strf(item.title) : filename;
|
||||||
|
$: author = item.authors ? (
|
||||||
|
Array.isArray(item.authors) ?
|
||||||
|
item.authors[0]:
|
||||||
|
typeof item.authors === 'string' ?
|
||||||
|
item.authors:
|
||||||
|
"unknown author"):
|
||||||
|
album.authors ? (
|
||||||
|
Array.isArray(album.authors) ?
|
||||||
|
album.authors[0]:
|
||||||
|
typeof album.authors === 'string' ?
|
||||||
|
album.authors:
|
||||||
|
"unknown author"):
|
||||||
|
"Luca Bosin";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a href={src} on:click={clickHandler}>
|
<li>
|
||||||
|
<figure style="--image: url('{src}/t/3')">
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(min-width: 850px)" srcset="{src}/t/l" />
|
<source media="(min-width: 2560px)" srcset="{src}/t/l" />
|
||||||
<source media="(min-width: 450px)" srcset="{src}/t/m" />
|
<source media="(min-width: 1600px)" srcset="{src}/t/m" />
|
||||||
<img src="{src}/t" {alt} loading={firstViewport ? 'eager' : 'lazy'} />
|
<img src="{src}/t" {alt} loading={lazy ? 'lazy' : 'eager'} />
|
||||||
</picture>
|
</picture>
|
||||||
|
<figcaption>
|
||||||
|
<b>{title}</b>
|
||||||
|
<cite>{author}</cite>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<a href={src} on:click={clickHandler} on:contextmenu={rightClickHandler}>
|
||||||
|
<Icon class="icon" mdi="arrow-expand" size={2.25}/>
|
||||||
</a>
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
li {
|
||||||
|
position: relative;
|
||||||
|
height: fit-content;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 30vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
width: 30vw;
|
||||||
|
height: 20vw;
|
||||||
|
background-color: rgba(0,0,0,.25);
|
||||||
|
background-image: var(--image);
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 30vw;
|
||||||
|
height: 20vw;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
display: grid;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 1em;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .5s;
|
||||||
|
z-index: 1;
|
||||||
|
gap: .25em;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
cite {
|
||||||
|
font-size: .75em;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: grid;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0,0,0,.5);
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .5s;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover :is(figcaption, a) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
2
src/lib/icons/arrow-expand.js
Normal file
2
src/lib/icons/arrow-expand.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
const path = 'M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z';
|
||||||
|
export default path;
|
||||||
2
src/lib/icons/arrow-left.js
Normal file
2
src/lib/icons/arrow-left.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
const path = 'M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z';
|
||||||
|
export default path;
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { str, strf } from '$lib/data/language.js';
|
import { strf } from '$lib/data/language.js';
|
||||||
|
|
||||||
import Header from '$lib/components/Header.svelte';
|
import Header from '$lib/components/Header.svelte';
|
||||||
import Gallery from '$lib/components/Gallery.svelte';
|
import Gallery from '$lib/components/Gallery.svelte';
|
||||||
@ -17,4 +17,6 @@
|
|||||||
<b>Sorting Date:</b> {data.album.date}<br />
|
<b>Sorting Date:</b> {data.album.date}<br />
|
||||||
<b>License:</b> {data.album.license}<br />
|
<b>License:</b> {data.album.license}<br />
|
||||||
</p>
|
</p>
|
||||||
<Gallery items={data.album.items} base={`${data.base}/i/`} />
|
<main>
|
||||||
|
<Gallery album={data.album} base={`${data.base}/i/`} />
|
||||||
|
</main>
|
||||||
|
|||||||
@ -20,12 +20,12 @@ export async function GET({ params }) {
|
|||||||
} else if (params.width === 'l') {
|
} else if (params.width === 'l') {
|
||||||
width = 1200;
|
width = 1200;
|
||||||
} else if (!Number.isNaN(Number(params.width))) {
|
} else if (!Number.isNaN(Number(params.width))) {
|
||||||
width = Number(width);
|
width = Number(params.width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thumbnail = thumbnail || await sharp(content).resize(width).webp({ quality: 90 }).toBuffer();
|
thumbnail = thumbnail || await sharp(content).resize(width).webp({ quality: 90 }).toBuffer();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`${err.stack}`.replaceAll('/home/sveltekit', '.'));
|
console.error(`${/** @type {Error} */(err).stack}`.replaceAll('/home/sveltekit', '.'));
|
||||||
throw error(500, 'Error getting thumbnail');
|
throw error(500, 'Error getting thumbnail');
|
||||||
}
|
}
|
||||||
return new Response(thumbnail, {
|
return new Response(thumbnail, {
|
||||||
|
|||||||
Reference in New Issue
Block a user