let gallery; let sentinel; let sortInfo; let observer; let offset; let loading = false; let hasMore = true; const targetHeight = window.innerWidth > 1600 ? 280 : 220; const limit = window.innerWidth > 1600 ? 50 : 20; const urlParams = new URLSearchParams(window.location.search); const sort = urlParams.get("sort") || "name"; async function loadMoreImages() { if (loading || !hasMore) return; // 加载期间先取消观察 observer.unobserve(sentinel); loading = true; try { const res = await fetch( `/api/images?offset=${offset}&limit=${limit}&height=${targetHeight}&sort=${sort}` ); if (!res.ok) throw new Error("Network error"); const data = await res.json(); appendImages(data.images); hasMore = data.offset + data.images.length < data.total; offset += data.images.length; } catch (err) { console.error(err); } finally { loading = false; // 加载完成下一帧重新观察,强制刷新交叉状态 requestAnimationFrame(() => { observer.observe(sentinel); }); sortInfo.textContent = sort; } } function appendImages(items) { const fragment = document.createDocumentFragment(); for (const item of items) { const wrapper = document.createElement("div"); wrapper.style.width = item.j_width + "px"; wrapper.style.flexGrow = item.j_width; const i = document.createElement("i"); i.style.paddingBottom = item.j_padding + "%"; const span = document.createElement("span"); const p = document.createElement("p"); p.textContent = `${item.long}px | ${item.size}`; span.appendChild(p); i.appendChild(span); wrapper.appendChild(i); const img = document.createElement("img"); img.name = item.file_name; img.alt = `${item.width}*${item.height} | ${item.size} | ${item.format} `; img.loading = "lazy"; img.decoding = "async"; if (item.preview_url) { img.src = item.preview_url; img.dataset.highres = item.url; } else { img.src = item.url; } wrapper.appendChild(img); fragment.appendChild(wrapper); } gallery.appendChild(fragment); // gallery.insertBefore(fragment, sentinel); } document.addEventListener("DOMContentLoaded", () => { gallery = document.getElementById("gallery"); sentinel = document.getElementById("sentinel"); sortInfo = document.getElementById("sort-info"); offset = gallery.childElementCount - 1; observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { loadMoreImages(); } }, { root: null, rootMargin: "800px", // 提前 800px 加载 threshold: 0, } ); observer.observe(sentinel); });