|
|
@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export type AnchorScrollType = {
|
|
|
|
|
|
|
|
el: HTMLElement;
|
|
|
|
|
|
|
|
currentIndex: number;
|
|
|
|
|
|
|
|
container: string;
|
|
|
|
|
|
|
|
offsetTop?: number;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function useAnchorScroll({
|
|
|
|
|
|
|
|
el, // 当前元素
|
|
|
|
|
|
|
|
currentIndex, // 当前index值
|
|
|
|
|
|
|
|
container, // 所有锚点的父元素容器
|
|
|
|
|
|
|
|
offsetTop = 0 // 偏移量
|
|
|
|
|
|
|
|
}: AnchorScrollType) {
|
|
|
|
|
|
|
|
let isClickRef = useRef(false);
|
|
|
|
|
|
|
|
let timer: any = useRef(null);
|
|
|
|
|
|
|
|
const [newIndex, setNewIndex] = useState(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function clickHandler() {
|
|
|
|
|
|
|
|
if (el) {
|
|
|
|
|
|
|
|
window.scroll({
|
|
|
|
|
|
|
|
top: el.offsetTop - offsetTop,
|
|
|
|
|
|
|
|
behavior: "smooth"
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
setNewIndex(currentIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isClickRef.current = true;
|
|
|
|
|
|
|
|
if (timer.current) clearTimeout(timer.current);
|
|
|
|
|
|
|
|
timer.current = setTimeout(() => {
|
|
|
|
|
|
|
|
isClickRef.current = false;
|
|
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function scrollHanlder() {
|
|
|
|
|
|
|
|
if (isClickRef.current) return;
|
|
|
|
|
|
|
|
const navContents = document.querySelectorAll(container);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const offsetTopArr = [] as any;
|
|
|
|
|
|
|
|
navContents.forEach((item: any) => {
|
|
|
|
|
|
|
|
offsetTopArr.push(item.offsetTop);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let n = 0; n < offsetTopArr.length; n++) {
|
|
|
|
|
|
|
|
if (scrollTop + offsetTop >= offsetTopArr[n]) {
|
|
|
|
|
|
|
|
setNewIndex(n);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
if (newIndex === currentIndex) return;
|
|
|
|
|
|
|
|
clickHandler();
|
|
|
|
|
|
|
|
}, [el, currentIndex]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
window.addEventListener("scroll", scrollHanlder);
|
|
|
|
|
|
|
|
return () => window.removeEventListener("scroll", scrollHanlder);
|
|
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return newIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 在组件页面使用修改为以下方式:
|
|
|
|
|
|
|
|
// import { useAnchorScroll } from './hooks';
|
|
|
|
|
|
|
|
// const [currentIndex, setCurrentIndex] = React.useState<any>(0);
|
|
|
|
|
|
|
|
// const [el, setEl] = React.useState<any>(null);
|
|
|
|
|
|
|
|
// const newIndex = useAnchorScroll({
|
|
|
|
|
|
|
|
// el,
|
|
|
|
|
|
|
|
// currentIndex,
|
|
|
|
|
|
|
|
// container: '.module-content',
|
|
|
|
|
|
|
|
// offsetTop: 130,
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// !!!注意:slide-bar部分修改为newIndex
|
|
|
|
|
|
|
|
// <div
|
|
|
|
|
|
|
|
// className={`slide-bar slide-bar-${newIndex}`}
|
|
|
|
|
|
|
|
// style={{ top: `${newIndex * 48}px` }}
|
|
|
|
|
|
|
|
// ></div>
|