diff options
| author | david <[email protected]> | 2026-10-10 15:23:43 -0300 |
|---|---|---|
| committer | david <[email protected]> | 2026-10-10 15:23:43 -0300 |
| commit | 15df6f2608dc18a2707e5f9fb694c2766fd0dab1 (patch) | |
| tree | 3493ce6ad4fc67234c017cef0d0b36a2d1033fae /scripts | |
| parent | fbfb3f1a44185acb94b756930b9c62d1ec58bafb (diff) | |
| download | webpage-main.tar.gz webpage-main.zip | |
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/justifiedgallery.js | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/scripts/justifiedgallery.js b/scripts/justifiedgallery.js index 0d8c2e1..690bd49 100644 --- a/scripts/justifiedgallery.js +++ b/scripts/justifiedgallery.js @@ -8,7 +8,8 @@ rowHeight: 80, //target row height (px)
margins: 2, //gap between images (px)
maxRowHeight: '150%', //cap on stretched row height
- lastRow: 'nojustify' //how to handle the final incomplete row
+ lastRow: 'nojustify', //how to handle the final incomplete row
+ trickleMs: 1000 //before any scroll: load 1 image per this many ms
};
const galleryEl = document.getElementById('gallery');
@@ -55,6 +56,37 @@ const res = await fetch(CONFIG.manifest);
const items = await res.json();
+ const pending = []; // imgs still waiting for a src, in order
+ let unlocked = false;
+
+ function startLoad(img) {
+ const src = img.dataset.src;
+ if (!src) return;
+ delete img.dataset.src;
+ const reveal = () => img.parentNode.classList.add('jg-entry-visible');
+ img.addEventListener('load', reveal, { once: true });
+ img.addEventListener('error', reveal, { once: true });
+ img.src = src;
+ }
+
+ // before the first scroll: 1 image per CONFIG.trickleMs
+ const trickle = setInterval(() => {
+ const img = pending.shift();
+ if (img) startLoad(img);
+ else clearInterval(trickle);
+ }, CONFIG.trickleMs);
+
+ // first scroll/wheel/touch anywhere (page or gallery box): release everything.
+ // img.loading='lazy' still makes the browser only fetch what's near the viewport.
+ function unlock() {
+ if (unlocked) return;
+ unlocked = true;
+ clearInterval(trickle);
+ pending.splice(0).forEach(startLoad);
+ }
+ ['scroll', 'wheel', 'touchmove'].forEach(ev =>
+ window.addEventListener(ev, unlock, { passive: true, capture: true, once: true }));
+
items.forEach(({ folder, file, width, height }) => {
const src = folder + file;
const thumbSrc = CONFIG.thumbFolder + folder + file.replace(CONFIG.imageExtensions, '.webp');
@@ -67,7 +99,8 @@ img.loading = 'lazy';
img.width = width;
img.height = height;
- img.src = thumbSrc;
+ img.dataset.src = thumbSrc; // real src is set later (trickle / first scroll)
+ pending.push(img);
entry.appendChild(img);
entry.addEventListener('click', async () => {
@@ -83,7 +116,8 @@ rowHeight: CONFIG.rowHeight,
margins: CONFIG.margins,
maxRowHeight: CONFIG.maxRowHeight,
- lastRow: CONFIG.lastRow
+ lastRow: CONFIG.lastRow,
+ waitThumbnailsLoad: false // lay out from width/height attrs, no src needed
});
}
@@ -322,6 +356,7 @@ const justifiedGallery = (function () { captionFromEntry(entry) {
const captions = Array.from(entry.querySelectorAll('.jg-caption'));
+
return captions.find(el => el.parentNode === entry) || null;
}
|
