portfolio : fix gallery loading and optimize image sizes refs #59
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s
- Remove GalleryAnimation preloading (was downloading full-size originals via new Image(), causing 5MB+ redundant downloads on top of WebP srcset) - Gallery now shows immediately, images load lazily via DOM - Force eager loading on mockup img when slide becomes active (fixes first-project gallery never showing — lazy img off-screen on bg slide) - Resize all direct ->url() calls to appropriate display dimensions: gallery src 600px, mockup src 960px, backgrounds 1920px, play lettering 500px, play preview 1000px, team photos 400px Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3d8d709165
commit
689ec3b138
5 changed files with 21 additions and 26 deletions
|
|
@ -18,7 +18,7 @@ $specificData = [
|
|||
return [
|
||||
'name' => $file->memberName()->value(),
|
||||
'role' => $file->role()->value(),
|
||||
'photo' => $file->url(),
|
||||
'photo' => $file->resize(400, null, 80)->url(),
|
||||
'link' => $file->link()->value() ?: null,
|
||||
];
|
||||
})->values()
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ $specificData = [
|
|||
return [
|
||||
'title' => $game->title()->value(),
|
||||
'slug' => $game->slug(),
|
||||
'lettering' => $game->lettering()->toFile()?->url(),
|
||||
'lettering' => $game->lettering()->toFile()?->resize(500, null, 80)->url(),
|
||||
'description' => $game->description()->value(),
|
||||
'thumbnail' => $game->thumbnail()->toFile()?->url(),
|
||||
'thumbnailSrcset' => $game->thumbnail()->toFile()?->srcset('thumbnail'),
|
||||
'thumbnailWebp' => $game->thumbnail()->toFile()?->srcset('thumbnail-webp'),
|
||||
'backgroundImage' => $game->backgroundImage()->toFile()?->url(),
|
||||
'preview' => $game->preview()->toFile()?->url(),
|
||||
'backgroundImage' => $game->backgroundImage()->toFile()?->resize(1920, null, 80)->url(),
|
||||
'preview' => $game->preview()->toFile()?->resize(1000, null, 80)->url(),
|
||||
'playLink' => $game->playLink()->value() ?: null,
|
||||
];
|
||||
})->values()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
$defaultLang = kirby()->defaultLanguage()->code();
|
||||
|
||||
$specificData = [
|
||||
'backgroundImage' => $page->backgroundImage()->toFile()?->url(),
|
||||
'backgroundImage' => $page->backgroundImage()->toFile()?->resize(1920, null, 80)->url(),
|
||||
'projects' => $page->children()->listed()->map(function($project) use ($defaultLang) {
|
||||
$mockupFile = $project->content($defaultLang)->mockup()->toFile();
|
||||
return [
|
||||
|
|
@ -13,18 +13,18 @@ $specificData = [
|
|||
'description' => $project->description()->value(),
|
||||
'thumbnail' => $project->thumbnail()->toFile()?->resize(160, null, 80)->url(),
|
||||
'imagesGallery' => $project->imagesGallery()->toFiles()->map(fn($f) => [
|
||||
'src' => $f->url(),
|
||||
'src' => $f->resize(600, null, 80)->url(),
|
||||
'srcset' => $f->srcset('gallery'),
|
||||
'webp' => $f->srcset('gallery-webp'),
|
||||
])->values(),
|
||||
'mockup' => $mockupFile?->url(),
|
||||
'mockup' => $mockupFile?->resize(960, null, 80)->url(),
|
||||
'mockupSrcset' => $mockupFile?->srcset('mockup'),
|
||||
'mockupWebp' => $mockupFile?->srcset('mockup-webp'),
|
||||
'galleryAnimationMode' => $project->galleryAnimationMode()->value() ?: 'vertical',
|
||||
'mockupPosition' => $project->mockupPosition()->value() ?: 'center',
|
||||
'secondsPerImage' => $project->secondsPerImage()->isNotEmpty() ? (int) $project->secondsPerImage()->value() : 8,
|
||||
'galleryBackgroundColor' => $project->galleryBackgroundColor()->value(),
|
||||
'galleryBackgroundImage' => $project->galleryBackgroundImage()->isNotEmpty() ? $project->galleryBackgroundImage()->toFile()->url() : null,
|
||||
'galleryBackgroundImage' => $project->galleryBackgroundImage()->isNotEmpty() ? $project->galleryBackgroundImage()->toFile()->resize(1200, null, 80)->url() : null,
|
||||
'keywords' => $project->keywords()->toStructure()->map(fn($i) => [
|
||||
'label' => $i->label()->value(),
|
||||
'text' => $i->text()->value(),
|
||||
|
|
|
|||
|
|
@ -15,25 +15,10 @@
|
|||
let allLoaded = $state(false)
|
||||
let needsFade = $state(false)
|
||||
|
||||
// Wait for all unique source images to load before revealing
|
||||
// Show immediately — the DOM images load via lazy loading when visible.
|
||||
// No explicit preloading: it was forcing full-size originals to download.
|
||||
onMount(() => {
|
||||
const uniqueSrcs = new Set(images.map(img => img.src).filter(Boolean))
|
||||
if (uniqueSrcs.size === 0) { allLoaded = true; return }
|
||||
|
||||
let remaining = uniqueSrcs.size
|
||||
const done = () => { if (--remaining <= 0) allLoaded = true }
|
||||
|
||||
for (const src of uniqueSrcs) {
|
||||
const img = new Image()
|
||||
img.src = src
|
||||
if (img.complete) {
|
||||
done()
|
||||
} else {
|
||||
needsFade = true
|
||||
img.onload = done
|
||||
img.onerror = done
|
||||
}
|
||||
}
|
||||
allLoaded = true
|
||||
})
|
||||
|
||||
const columns = $derived.by(() => {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,16 @@
|
|||
return () => img.removeEventListener('load', onLoad)
|
||||
})
|
||||
|
||||
// Force le chargement du mockup quand la slide devient active :
|
||||
// Si l'image est lazy et a été rendue off-screen (slide en arrière-plan),
|
||||
// le browser ne la charge pas → mockupReady reste false → galerie jamais affichée.
|
||||
$effect(() => {
|
||||
if (!isActive || mockupReady || !mockupEl) return
|
||||
const img = mockupEl.querySelector('img')
|
||||
if (!img || img.complete) return
|
||||
img.loading = 'eager'
|
||||
})
|
||||
|
||||
// --- Effect: reset when slide deactivated ---
|
||||
// wasActive évite que clearAnchor() s'exécute au montage initial
|
||||
// (isActive est false avant l'initialisation des slides)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue