Add image load animation

main
trivernis 1 year ago
parent ae6d3f818f
commit 22083f7b7c
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 KiB

@ -3,6 +3,7 @@ name = "Dracaena Fragrans"
bin_name = "Dracaena Fragrans" bin_name = "Dracaena Fragrans"
[image] [image]
local = "dracaena-fragrans.jpg"
remote = "https://upload.wikimedia.org/wikipedia/commons/6/64/Dracaena_fragrans_a1.jpg" remote = "https://upload.wikimedia.org/wikipedia/commons/6/64/Dracaena_fragrans_a1.jpg"
source = "https://commons.wikimedia.org/wiki/File:Dracaena_fragrans_a1.jpg" source = "https://commons.wikimedia.org/wiki/File:Dracaena_fragrans_a1.jpg"
alt = """ alt = """

@ -3,6 +3,7 @@ name = "Monstera Deliciosa"
bin_name = "Monstera Deliciosa" bin_name = "Monstera Deliciosa"
[image] [image]
local = "monstera-deliciosa.jpg"
remote = "https://upload.wikimedia.org/wikipedia/commons/d/d4/New_Monstera_Deliciosa_Leaf.jpg" remote = "https://upload.wikimedia.org/wikipedia/commons/d/d4/New_Monstera_Deliciosa_Leaf.jpg"
format = "jpeg" format = "jpeg"
width = 1512 width = 1512

@ -0,0 +1,65 @@
<script context="module" lang="ts">
export type Source = {
img: { src: string; w?: number; h?: number };
} & {
[key: string]: { src: string; w?: number; h?: number }[];
};
</script>
<script lang="ts">
import Img from "@zerodevx/svelte-img";
import { onMount } from "svelte";
export let src: Source | any;
export let alt: string;
let imgref: Img;
let loaded: boolean = false;
onMount(() => {
if (imgref && imgref.complete) loaded = true;
});
</script>
<Img bind:imgref {src} {alt} {...$$restProps} on:load={() => (loaded = true)} />
<div class="blur" class:loaded />
<style lang="scss">
@use "../../colors.scss";
@use "sass:color";
.blur {
position: absolute;
inset: 0;
backdrop-filter: blur(20px);
pointer-events: none;
transition-duration: 0.8s;
opacity: 1;
animation: loading;
animation-duration: 0.8s;
animation-iteration-count: infinite;
}
.loaded {
opacity: 0;
animation: fade 2s bezier;
}
@keyframes fade {
0%,
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes loading {
0%,
100% {
background: rgba(0, 0, 0, 0);
}
50% {
background: color.adjust(colors.$background, $alpha: -0.8);
}
}
</style>

@ -2,6 +2,21 @@
import Footer from "./Footer.svelte"; import Footer from "./Footer.svelte";
import Header from "./Header.svelte"; import Header from "./Header.svelte";
import "../app.scss"; import "../app.scss";
import { onNavigate } from "$app/navigation";
onNavigate((navigation) => {
// @ts-expect-error
if (!document.startViewTransition) return;
return new Promise((resolve) => {
// @ts-expect-error
document.startViewTransition(async () => {
resolve();
await navigation.complete;
});
});
});
</script> </script>
<Header /> <Header />

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import LazyImage from "$lib/components/LazyImage.svelte";
import { plants } from "$lib/plants"; import { plants } from "$lib/plants";
import Img from "@zerodevx/svelte-img";
const images = import.meta.glob("$lib/assets/images/*.{png,jpg,jpeg,webp}", { const images = import.meta.glob("$lib/assets/images/*.{png,jpg,jpeg,webp}", {
import: "default", import: "default",
eager: true, eager: true,
query: { w: 256, h: 128, fit: "cover", as: "run:2", normalize: true }, query: { w: 256, h: 128, fit: "cover", as: "run", normalize: true },
}); });
</script> </script>
@ -14,7 +14,7 @@
<div class="plant-item-wrapper"> <div class="plant-item-wrapper">
<div class="plant-item"> <div class="plant-item">
<a class="plant-link" href="/plants/{plant.slug}"> <a class="plant-link" href="/plants/{plant.slug}">
<Img <LazyImage
class="sv-image" class="sv-image"
src={images[`/src/lib/assets/images/${plant.image.local}`] ?? { src={images[`/src/lib/assets/images/${plant.image.local}`] ?? {
img: { src: plant.image.remote, w: plant.image.width }, img: { src: plant.image.remote, w: plant.image.width },

@ -1,13 +1,13 @@
<script lang="ts"> <script lang="ts">
import LazyImage from "$lib/components/LazyImage.svelte";
import type { PlantData } from "$lib/plants"; import type { PlantData } from "$lib/plants";
import Img from "@zerodevx/svelte-img";
export let image: PlantData["image"]; export let image: PlantData["image"];
const images = import.meta.glob("$lib/assets/images/*.{png,jpg,jpeg,webp}", { const images = import.meta.glob("$lib/assets/images/*.{png,jpg,jpeg,webp}", {
import: "default", import: "default",
eager: true, eager: true,
query: { w: 1024, h: 512, fit: "cover", as: "run:2", normalize: true }, query: { w: 1024, h: 512, fit: "cover", as: "run", normalize: true },
}); });
const src = images[`/src/lib/assets/images/${image.local}`] ?? { const src = images[`/src/lib/assets/images/${image.local}`] ?? {
@ -20,7 +20,7 @@
<figure class="plant-image"> <figure class="plant-image">
<div class="image-wrap"> <div class="image-wrap">
<Img class="sv-image" {src} alt={image.alt} /> <LazyImage class="sv-image" {src} alt={image.alt} />
</div> </div>
{#if image.source != ""} {#if image.source != ""}
@ -70,11 +70,13 @@
background-color: colors.$highlight; background-color: colors.$highlight;
} }
} }
:global(.plant-image picture) { :global(.plant-image picture) {
width: 100%; width: 100%;
height: auto; height: auto;
aspect-ratio: 2 / 1; aspect-ratio: 2 / 1;
} }
:global(.sv-image) { :global(.sv-image) {
width: 100%; width: 100%;
height: auto; height: auto;

Loading…
Cancel
Save