mirror of
https://github.com/CaiJimmy/hugo-theme-stack.git
synced 2025-06-19 04:23:30 +08:00
Recompute offsets when window size changes
This commit is contained in:
parent
c1c64f190e
commit
ea3cc72085
@ -1,21 +1,14 @@
|
|||||||
// Implements a scroll spy system for the ToC, displaying the current section with an indicator and scrolling to it when needed.
|
// Implements a scroll spy system for the ToC, displaying the current section with an indicator and scrolling to it when needed.
|
||||||
|
|
||||||
// While solutions for debouncing like the ones in https://gomakethings.com/debouncing-your-javascript-events/ could work,
|
// Inspired from https://gomakethings.com/debouncing-your-javascript-events/ could work
|
||||||
// we do need an actual debouncing of scroll events in order to only capture the "end" of the scroll.
|
|
||||||
function debounced(func: Function) {
|
function debounced(func: Function) {
|
||||||
let timeout;
|
let timeout;
|
||||||
return (e: Event) => {
|
return () => {
|
||||||
/*
|
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
timeout = window.requestAnimationFrame(func);
|
|
||||||
*/
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
window.cancelAnimationFrame(timeout);
|
window.cancelAnimationFrame(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = window.requestAnimationFrame(() => func(e));
|
timeout = window.requestAnimationFrame(() => func());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +37,13 @@ function findLinkForSectionId(sectionId: string, navigation: NodeListOf<Element>
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function computeOffsets(headers: NodeListOf<Element>) {
|
||||||
|
let sectionsOffsets = [];
|
||||||
|
headers.forEach((header: HTMLElement) => { sectionsOffsets.push({ id: header.id, offset: header.offsetTop }) });
|
||||||
|
sectionsOffsets.sort((a, b) => a.offset - b.offset);
|
||||||
|
return sectionsOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
function setupScrollspy() {
|
function setupScrollspy() {
|
||||||
let headers = document.querySelectorAll(headersQuery);
|
let headers = document.querySelectorAll(headersQuery);
|
||||||
if (!headers) {
|
if (!headers) {
|
||||||
@ -63,10 +63,7 @@ function setupScrollspy() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sectionsOffsets = [];
|
let sectionsOffsets = computeOffsets(headers);
|
||||||
|
|
||||||
headers.forEach((header: HTMLElement) => { sectionsOffsets.push({ id: header.id, offset: header.offsetTop }) });
|
|
||||||
sectionsOffsets.sort((a, b) => a.offset - b.offset);
|
|
||||||
|
|
||||||
// We need to avoid scrolling when the user is actively interacting with the ToC. Otherwise, if the user clicks on a link in the ToC,
|
// We need to avoid scrolling when the user is actively interacting with the ToC. Otherwise, if the user clicks on a link in the ToC,
|
||||||
// we would scroll their view, which is not optimal usability-wise.
|
// we would scroll their view, which is not optimal usability-wise.
|
||||||
@ -76,7 +73,8 @@ function setupScrollspy() {
|
|||||||
|
|
||||||
let activeSectionLink: Element;
|
let activeSectionLink: Element;
|
||||||
|
|
||||||
function scrollHandler(e: Event) {
|
function scrollHandler() {
|
||||||
|
console.log("scroll!");
|
||||||
let scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
let scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
||||||
|
|
||||||
let newActiveSection: HTMLElement | undefined;
|
let newActiveSection: HTMLElement | undefined;
|
||||||
@ -99,7 +97,7 @@ function setupScrollspy() {
|
|||||||
|
|
||||||
if (newActiveSection && !newActiveSectionLink) {
|
if (newActiveSection && !newActiveSectionLink) {
|
||||||
// The active section does not have a link in the ToC, so we can't scroll to it.
|
// The active section does not have a link in the ToC, so we can't scroll to it.
|
||||||
console.warn("No link found for section", newActiveSection);
|
console.debug("No link found for section", newActiveSection);
|
||||||
} else if (newActiveSectionLink !== activeSectionLink) {
|
} else if (newActiveSectionLink !== activeSectionLink) {
|
||||||
if (activeSectionLink)
|
if (activeSectionLink)
|
||||||
activeSectionLink.classList.remove(activeClass);
|
activeSectionLink.classList.remove(activeClass);
|
||||||
@ -115,6 +113,14 @@ function setupScrollspy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("scroll", debounced(scrollHandler));
|
window.addEventListener("scroll", debounced(scrollHandler));
|
||||||
|
|
||||||
|
// Resizing may cause the offset values to change: recompute them.
|
||||||
|
function resizeHandler() {
|
||||||
|
sectionsOffsets = computeOffsets(headers);
|
||||||
|
scrollHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", debounced(resizeHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
export { setupScrollspy };
|
export { setupScrollspy };
|
Loading…
Reference in New Issue
Block a user