Glossary slider: use index-based scrollIntoView instead of scrollTo (more reliable with snap)
This commit is contained in:
parent
66e831f07f
commit
22137c6f90
59
index.html
59
index.html
@ -774,8 +774,7 @@ main {
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
scroll-snap-type: x mandatory;
|
scroll-snap-type: x proximity;
|
||||||
scroll-behavior: smooth;
|
|
||||||
padding: 4px 4px 12px;
|
padding: 4px 4px 12px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
@ -1741,42 +1740,42 @@ const SCHEDULE = [
|
|||||||
glossaryEl.appendChild(div);
|
glossaryEl.appendChild(div);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Slider controls
|
// Slider controls — index-based, uses scrollIntoView (more reliable than scrollTo with snap)
|
||||||
const glossPrev = document.getElementById('gloss-prev');
|
const glossPrev = document.getElementById('gloss-prev');
|
||||||
const glossNext = document.getElementById('gloss-next');
|
const glossNext = document.getElementById('gloss-next');
|
||||||
const glossCounter = document.getElementById('gloss-counter');
|
const glossCounter = document.getElementById('gloss-counter');
|
||||||
const totalCards = GLOSSARY.length;
|
const cards = Array.from(glossaryEl.querySelectorAll('.gloss-item'));
|
||||||
|
const totalCards = cards.length;
|
||||||
|
let currentIdx = 0;
|
||||||
|
|
||||||
function cardStep() {
|
function goTo(i) {
|
||||||
const firstCard = glossaryEl.querySelector('.gloss-item');
|
currentIdx = Math.max(0, Math.min(totalCards - 1, i));
|
||||||
if (!firstCard) return 0;
|
cards[currentIdx].scrollIntoView({ behavior: 'smooth', inline: 'start', block: 'nearest' });
|
||||||
const cs = window.getComputedStyle(glossaryEl);
|
updateNavState();
|
||||||
const gap = parseFloat(cs.columnGap || cs.gap || '12');
|
|
||||||
return firstCard.getBoundingClientRect().width + gap;
|
|
||||||
}
|
}
|
||||||
function currentIndex() {
|
function updateNavState() {
|
||||||
const step = cardStep();
|
glossCounter.textContent = `${currentIdx + 1} / ${totalCards}`;
|
||||||
return step ? Math.round(glossaryEl.scrollLeft / step) : 0;
|
glossPrev.disabled = currentIdx === 0;
|
||||||
|
glossNext.disabled = currentIdx === totalCards - 1;
|
||||||
}
|
}
|
||||||
function scrollToIndex(i) {
|
// Sync currentIdx when user scrolls manually (touch/trackpad)
|
||||||
const step = cardStep();
|
function syncFromScroll() {
|
||||||
const clamped = Math.max(0, Math.min(totalCards - 1, i));
|
const containerLeft = glossaryEl.getBoundingClientRect().left;
|
||||||
glossaryEl.scrollTo({ left: clamped * step, behavior: 'smooth' });
|
let bestIdx = 0, bestDist = Infinity;
|
||||||
}
|
for (let i = 0; i < cards.length; i++) {
|
||||||
function updateGlossNav() {
|
const d = Math.abs(cards[i].getBoundingClientRect().left - containerLeft);
|
||||||
const idx = currentIndex();
|
if (d < bestDist) { bestDist = d; bestIdx = i; }
|
||||||
glossCounter.textContent = `${idx + 1} / ${totalCards}`;
|
}
|
||||||
const maxScroll = glossaryEl.scrollWidth - glossaryEl.clientWidth;
|
if (bestIdx !== currentIdx) {
|
||||||
glossPrev.disabled = glossaryEl.scrollLeft <= 2;
|
currentIdx = bestIdx;
|
||||||
glossNext.disabled = glossaryEl.scrollLeft >= maxScroll - 2;
|
updateNavState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glossPrev.addEventListener('click', () => scrollToIndex(currentIndex() - 1));
|
glossPrev.addEventListener('click', () => goTo(currentIdx - 1));
|
||||||
glossNext.addEventListener('click', () => scrollToIndex(currentIndex() + 1));
|
glossNext.addEventListener('click', () => goTo(currentIdx + 1));
|
||||||
glossaryEl.addEventListener('scroll', updateGlossNav, { passive: true });
|
glossaryEl.addEventListener('scroll', syncFromScroll, { passive: true });
|
||||||
window.addEventListener('resize', updateGlossNav);
|
updateNavState();
|
||||||
// initial state after layout settles
|
|
||||||
requestAnimationFrame(updateGlossNav);
|
|
||||||
|
|
||||||
// Render projects
|
// Render projects
|
||||||
const projectsEl = document.getElementById('projects-grid');
|
const projectsEl = document.getElementById('projects-grid');
|
||||||
|
|||||||
Reference in New Issue
Block a user