1
1
"use client" ;
2
2
3
- import React , { useEffect , useState } from "react" ;
3
+ import React , { useEffect , useState , useRef } from "react" ;
4
4
import Link from "next/link" ;
5
5
import { Itoc } from "@/interfaces/Post" ;
6
6
import styles from "./TOC.module.css" ;
@@ -9,6 +9,7 @@ const TOC = ({ tocContent, ...props }: { tocContent: Array<Itoc> } & React.HTMLA
9
9
const stylesList = [ styles . toc_h1 , styles . toc_h2 , styles . toc_h3 , styles . toc_h4 , styles . toc_h5 ] ;
10
10
const { className, ...rest } = props ;
11
11
const [ activeId , setActiveId ] = useState < string | null > ( null ) ;
12
+ const containerRef = useRef < HTMLDivElement > ( null )
12
13
13
14
useEffect ( ( ) => {
14
15
const observer = new IntersectionObserver (
@@ -19,8 +20,8 @@ const TOC = ({ tocContent, ...props }: { tocContent: Array<Itoc> } & React.HTMLA
19
20
} ,
20
21
{
21
22
root : null ,
22
- rootMargin : "0px 0px -80 % 0px" ,
23
- threshold : 1. 0,
23
+ rootMargin : "0px 0px -50 % 0px" ,
24
+ threshold : 0 ,
24
25
} ,
25
26
) ;
26
27
const headingElements = tocContent . map ( ( toc ) => document . getElementById ( handleSlug ( toc . slug ) ) ) ;
@@ -34,8 +35,26 @@ const TOC = ({ tocContent, ...props }: { tocContent: Array<Itoc> } & React.HTMLA
34
35
} ;
35
36
} , [ tocContent ] ) ;
36
37
38
+ useEffect ( ( ) => {
39
+ if ( containerRef . current && activeId ) {
40
+ const element = document . getElementsByClassName ( styles . active ) [ 0 ] as HTMLElement ;
41
+ if ( element ) {
42
+ const container = containerRef . current ;
43
+ const containerHeight = container . clientHeight ;
44
+ const elementOffsetTop = element . offsetTop ;
45
+ const elementHeight = element . clientHeight ;
46
+
47
+ const scrollTop = elementOffsetTop - ( containerHeight / 2 ) + ( elementHeight / 2 ) ;
48
+ container . scrollTo ( {
49
+ top : scrollTop ,
50
+ behavior : "smooth" ,
51
+ } ) ;
52
+ }
53
+ }
54
+ } , [ activeId ] ) ;
55
+
37
56
return (
38
- < div className = { `${ styles . tocWrapper } ${ className || "" } ` } { ...rest } >
57
+ < div className = { `${ styles . tocWrapper } ${ className || "" } ` } ref = { containerRef } { ...rest } >
39
58
< div className = { styles . title } > 目录</ div >
40
59
{ tocContent . map ( ( value , index ) => {
41
60
const slug = handleSlug ( value . slug ) ;
0 commit comments