Skip to content

Instantly share code, notes, and snippets.

@jeiea
Created October 15, 2021 10:15
Show Gist options
  • Save jeiea/d1d1563de0285766a736ff2dcf38d370 to your computer and use it in GitHub Desktop.
Save jeiea/d1d1563de0285766a736ff2dcf38d370 to your computer and use it in GitHub Desktop.
const makePageNavigator = ref => {
let currentPage;
let ratio;
let ignoreIntersection = false;
const resetAnchor = entries => {
const container = ref.current;
if (!container?.clientHeight || entries.length === 0) {
return;
}
if (ignoreIntersection) {
ignoreIntersection = false;
return;
}
const page = 1;
const y = container.scrollTop + container.clientHeight / 2;
currentPage = page;
ratio = (y - page.offsetTop) / page.clientHeight;
};
const goNext = () => {
ignoreIntersection = false;
if (!currentPage) {
return;
}
const originBound = currentPage.getBoundingClientRect();
let cursor = currentPage;
while (cursor.nextElementSibling) {
const next = cursor.nextElementSibling;
const nextBound = next.getBoundingClientRect();
if (originBound.bottom < nextBound.top) {
next.scrollIntoView({ block: 'center' });
break;
}
cursor = next;
}
};
const goPrevious = () => {
ignoreIntersection = false;
if (!currentPage) {
return;
}
const originBound = currentPage.getBoundingClientRect();
let cursor = currentPage;
while (cursor.previousElementSibling) {
const previous = cursor.previousElementSibling;
const previousBound = previous.getBoundingClientRect();
if (previousBound.bottom < originBound.top) {
previous.scrollIntoView({ block: 'center' });
break;
}
cursor = previous;
}
};
const restoreScroll = () => {
const container = ref.current;
if (!container || ratio === undefined || currentPage === undefined) {
return;
}
const restoredY =
currentPage.offsetTop + currentPage.clientHeight * (ratio - 0.5);
container.scroll({ top: restoredY });
ignoreIntersection = true;
};
const intersectionOption = { threshold: [0.01, 0.5, 1] };
let observer;
const useInstance = () => {
observer = useIntersection(resetAnchor, intersectionOption);
useResize(ref.current, restoreScroll);
};
return {
get observer() {
return observer;
},
goNext,
goPrevious,
useInstance,
};
};
export const usePageNavigator = ref => {
const navigator = useMemo(() => makePageNavigator(ref), [ref]);
navigator.useInstance();
return navigator;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment