|
|
|
@@ -18,21 +18,15 @@ const ProfileImg = styled("img")({
|
|
|
|
|
width: 150,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const getTopOffset = (input: HTMLElement) => {
|
|
|
|
|
let el: HTMLElement | Element | null = input;
|
|
|
|
|
let o = 0;
|
|
|
|
|
do {
|
|
|
|
|
if (!(el instanceof HTMLElement)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const navBottomPadding = 50;
|
|
|
|
|
|
|
|
|
|
if (!isNaN(el.offsetTop)) {
|
|
|
|
|
o += el.offsetTop;
|
|
|
|
|
}
|
|
|
|
|
} while ((el = el.offsetParent));
|
|
|
|
|
const TopSpacer = styled("div")({
|
|
|
|
|
height: 40,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return o;
|
|
|
|
|
};
|
|
|
|
|
const StickyWrapper = styled("div")({
|
|
|
|
|
position: "sticky",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const MainNavigation: React.FC = () => {
|
|
|
|
|
const intl = useIntl();
|
|
|
|
@@ -45,64 +39,30 @@ const MainNavigation: React.FC = () => {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d.style.top = "0px";
|
|
|
|
|
|
|
|
|
|
let { height } = d.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
const listener = () => {
|
|
|
|
|
const visibleArea = navBottomPadding + height;
|
|
|
|
|
if (window.innerHeight > visibleArea) {
|
|
|
|
|
d.style.top = "0px";
|
|
|
|
|
} else {
|
|
|
|
|
d.style.top = `${window.innerHeight - visibleArea}px`;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const ro = new ResizeObserver((entries) => {
|
|
|
|
|
if (entries[0]) {
|
|
|
|
|
height = entries[0].contentRect.height;
|
|
|
|
|
listener();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ro.observe(d);
|
|
|
|
|
|
|
|
|
|
let scrollPrev = window.scrollY;
|
|
|
|
|
|
|
|
|
|
const listener = () => {
|
|
|
|
|
const down = scrollPrev < window.scrollY;
|
|
|
|
|
scrollPrev = window.scrollY;
|
|
|
|
|
const top = getTopOffset(d);
|
|
|
|
|
|
|
|
|
|
console.log({
|
|
|
|
|
"window.innerHeight": window.innerHeight,
|
|
|
|
|
height,
|
|
|
|
|
top,
|
|
|
|
|
down,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (window.innerHeight > height) {
|
|
|
|
|
d.style.marginTop = `${Math.max(window.scrollY, 0)}px`;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (down) {
|
|
|
|
|
const delta = top + height;
|
|
|
|
|
const wDelta = window.scrollY + window.innerHeight;
|
|
|
|
|
|
|
|
|
|
const diff = wDelta - delta;
|
|
|
|
|
console.log({ delta, wDelta, "window.scrollY": window.scrollY, diff });
|
|
|
|
|
|
|
|
|
|
if (diff > 0) {
|
|
|
|
|
const sizeDelta = Math.min(window.innerHeight - height, 0);
|
|
|
|
|
d.style.marginTop = `${Math.max(top + diff + sizeDelta, 0)}px`;
|
|
|
|
|
console.log({
|
|
|
|
|
sizeDelta,
|
|
|
|
|
marginTop: Math.max(top + diff + sizeDelta, 0),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const delta = top;
|
|
|
|
|
const wDelta = window.scrollY;
|
|
|
|
|
|
|
|
|
|
const diff = wDelta - delta;
|
|
|
|
|
console.log({ delta, wDelta, "window.scrollY": window.scrollY, diff });
|
|
|
|
|
if (diff < 0) {
|
|
|
|
|
console.log({ marginTop: Math.max(top + diff, 0) });
|
|
|
|
|
d.style.marginTop = `${Math.max(top + diff, 0)}px`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener("scroll", listener);
|
|
|
|
|
window.addEventListener("scroll", listener, { passive: true });
|
|
|
|
|
window.addEventListener("resize", listener, { passive: true });
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener("scroll", listener);
|
|
|
|
@@ -111,7 +71,8 @@ const MainNavigation: React.FC = () => {
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div ref={ref}>
|
|
|
|
|
<StickyWrapper ref={ref}>
|
|
|
|
|
<TopSpacer />
|
|
|
|
|
<ProfileImg src={profile} alt="profile picture" />
|
|
|
|
|
|
|
|
|
|
<NavigationHeadline>
|
|
|
|
@@ -177,7 +138,7 @@ const MainNavigation: React.FC = () => {
|
|
|
|
|
id: "Navigation.experience",
|
|
|
|
|
})}
|
|
|
|
|
</NavigationHeadline>
|
|
|
|
|
</div>
|
|
|
|
|
</StickyWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|