@@ -14,7 +14,7 @@ function clamp(v: number, min: number, max: number) {
1414 return Math . max ( min , Math . min ( max , v ) ) ;
1515}
1616
17- const SCROLL = 13000 ;
17+ const SCROLL = 4000 ;
1818const ITEMS = [ '表演' , '道具' , '灯光' , '音效' , '宣发美术' , '妆造' , '等等……' ] ;
1919
2020type Segment = { text : string ; red ?: boolean } ;
@@ -47,6 +47,9 @@ export default function ActivityDetailHTML(_props: Props) {
4747 const navigate = useNavigate ( ) ;
4848 const [ st , setSt ] = useState ( 0 ) ;
4949 const scrollRef = useRef < HTMLDivElement > ( null ) ;
50+ const autoRef = useRef ( false ) ;
51+ const autoRaf = useRef ( 0 ) ;
52+ const userScrolled = useRef ( false ) ;
5053 const [ scale , setScale ] = useState ( 1 ) ;
5154 const [ page2Boost , setPage2Boost ] = useState ( 1 ) ;
5255 const [ page4Boost , setPage4Boost ] = useState ( 1 ) ;
@@ -70,6 +73,7 @@ export default function ActivityDetailHTML(_props: Props) {
7073 if ( saved && scrollRef . current ) {
7174 scrollRef . current . scrollTop = Number ( saved ) ;
7275 sessionStorage . removeItem ( SCROLL_KEY ) ;
76+ userScrolled . current = true ;
7377 }
7478 } , [ ] ) ;
7579
@@ -104,6 +108,39 @@ export default function ActivityDetailHTML(_props: Props) {
104108 setSt ( scrollRef . current ?. scrollTop ?? 0 ) ;
105109 } , [ ] ) ;
106110
111+ useEffect ( ( ) => {
112+ const el = scrollRef . current ;
113+ if ( ! el ) return ;
114+
115+ const onUserScroll = ( ) => { userScrolled . current = true ; } ;
116+ el . addEventListener ( 'wheel' , onUserScroll , { passive : true } ) ;
117+ el . addEventListener ( 'touchstart' , onUserScroll , { passive : true } ) ;
118+
119+ const timer = setTimeout ( ( ) => {
120+ if ( userScrolled . current || ( el . scrollTop > 5 ) ) return ;
121+ const speed = 3.75 ; // px per frame
122+
123+ const tick = ( ) => {
124+ if ( userScrolled . current ) return ;
125+ const el = scrollRef . current ;
126+ if ( ! el ) return ;
127+ autoRef . current = true ;
128+ el . scrollTop += speed ;
129+ autoRef . current = false ;
130+ if ( el . scrollTop >= el . scrollHeight - el . clientHeight - 2 ) return ;
131+ autoRaf . current = requestAnimationFrame ( tick ) ;
132+ } ;
133+ autoRaf . current = requestAnimationFrame ( tick ) ;
134+ } , 500 ) ;
135+
136+ return ( ) => {
137+ el . removeEventListener ( 'wheel' , onUserScroll ) ;
138+ el . removeEventListener ( 'touchstart' , onUserScroll ) ;
139+ clearTimeout ( timer ) ;
140+ cancelAnimationFrame ( autoRaf . current ) ;
141+ } ;
142+ } , [ ] ) ;
143+
107144 const goToClub = useCallback ( ( ) => {
108145 sessionStorage . setItem ( SCROLL_KEY , String ( scrollRef . current ?. scrollTop ?? 0 ) ) ;
109146 navigate ( '/club/15' , { state : { fromActivity : true } } ) ;
@@ -173,7 +210,7 @@ export default function ActivityDetailHTML(_props: Props) {
173210 } }
174211 >
175212 < style > { `@font-face{font-family:STZhongsong;src:url(${ asset ( '/fonts/stzhongsong.ttf' ) } ) format('truetype');font-weight:normal;font-style:normal;font-display:swap;}` } </ style >
176- < div style = { { height : SCROLL } } />
213+ < div style = { { height : `calc( ${ SCROLL } px + 100vh)` } } />
177214
178215 < div
179216 className = "pointer-events-none fixed inset-0 z-10 flex items-center justify-center px-6"
0 commit comments