@@ -19,11 +19,14 @@ import { calculateDimensions } from '~/utils/images'
19
19
import type { MImageType } from '../../utils/image'
20
20
import styles from './index.module.css'
21
21
22
+ const IMAGE_CONTAINER_MARGIN_INSET = 60
23
+ const CHILD_GAP = 15
24
+ const AUTOPLAY_DURATION = 5000
25
+
22
26
interface GalleryProps {
23
27
images : MImageType [ ]
24
28
}
25
- const IMAGE_CONTAINER_MARGIN_INSET = 60
26
- const CHILD_GAP = 15
29
+
27
30
export const Gallery : FC < GalleryProps > = ( props ) => {
28
31
const { images } = props
29
32
const imageMeta = useContext ( ImageSizeMetaContext )
@@ -69,7 +72,7 @@ export const Gallery: FC<GalleryProps> = (props) => {
69
72
70
73
// eslint-disable-next-line react-hooks/exhaustive-deps
71
74
const handleOnScroll : UIEventHandler < HTMLDivElement > = useCallback (
72
- throttle ( ( e ) => {
75
+ throttle < UIEventHandler < HTMLDivElement > > ( ( e ) => {
73
76
const $ = e . target as HTMLDivElement
74
77
75
78
const index = Math . floor (
@@ -81,15 +84,14 @@ export const Gallery: FC<GalleryProps> = (props) => {
81
84
[ ] ,
82
85
)
83
86
const handleScrollTo = useCallback (
84
- ( i : number , animated = true ) => {
85
- autoplayTimerRef . current = clearInterval ( autoplayTimerRef . current )
87
+ ( i : number ) => {
86
88
if ( ! containerRef ) {
87
89
return
88
90
}
89
91
90
92
containerRef . scrollTo ( {
91
93
left : memoedChildContainerWidthRef . current * i ,
92
- behavior : animated ? 'smooth' : 'auto ',
94
+ behavior : 'smooth' ,
93
95
} )
94
96
} ,
95
97
[ containerRef ] ,
@@ -98,14 +100,43 @@ export const Gallery: FC<GalleryProps> = (props) => {
98
100
const autoplayTimerRef = useRef ( null as any )
99
101
100
102
const currentIndexRef = useStateRef ( currentIndex )
103
+ const totalImageLengthRef = useStateRef ( images . length )
104
+
105
+ // 向后翻页状态
106
+ const isForward = useRef ( true )
107
+
108
+ const autoplayRef = useRef ( true )
109
+ const handleCancelAutoplay = useCallback ( ( ) => {
110
+ if ( ! autoplayRef . current ) {
111
+ return
112
+ }
113
+
114
+ autoplayRef . current = false
115
+ clearInterval ( autoplayTimerRef . current )
116
+ } , [ ] )
117
+
101
118
const { ref } = useInView ( {
102
119
initialInView : false ,
120
+ triggerOnce : images . length < 2 ,
103
121
onChange ( inView ) {
122
+ if ( totalImageLengthRef . current < 2 || ! autoplayRef . current ) {
123
+ return
124
+ }
104
125
if ( inView ) {
105
126
autoplayTimerRef . current = setInterval ( ( ) => {
106
- const index = ( currentIndexRef . current + 1 ) % images . length
107
- handleScrollTo ( index , index == 0 ? false : true )
108
- } , 3000 )
127
+ if (
128
+ currentIndexRef . current + 1 > totalImageLengthRef . current - 1 &&
129
+ isForward . current
130
+ ) {
131
+ isForward . current = false
132
+ }
133
+ if ( currentIndexRef . current - 1 < 0 && ! isForward . current ) {
134
+ isForward . current = true
135
+ }
136
+
137
+ const index = currentIndexRef . current + ( isForward . current ? 1 : - 1 )
138
+ handleScrollTo ( index )
139
+ } , AUTOPLAY_DURATION )
109
140
} else {
110
141
autoplayTimerRef . current = clearInterval ( autoplayTimerRef . current )
111
142
}
@@ -119,7 +150,12 @@ export const Gallery: FC<GalleryProps> = (props) => {
119
150
} , [ ] )
120
151
121
152
return (
122
- < div className = { clsx ( 'w-full' , 'relative' ) } ref = { ref } >
153
+ < div
154
+ className = { clsx ( 'w-full' , 'relative' , styles [ 'root' ] ) }
155
+ ref = { ref }
156
+ onWheel = { handleCancelAutoplay }
157
+ onTouchStart = { handleCancelAutoplay }
158
+ >
123
159
< div
124
160
className = { clsx (
125
161
'w-full whitespace-nowrap overflow-auto' ,
@@ -173,7 +209,7 @@ export const Gallery: FC<GalleryProps> = (props) => {
173
209
return (
174
210
< div
175
211
className = { clsx (
176
- 'h-[6px] w-[6px] rounded-full bg-light-font opacity-50 transition-opacity duration-200 ease-in-out cursor-pointer' ,
212
+ 'h-[6px] w-[6px] rounded-full bg-dark-50 opacity-50 transition-opacity duration-200 ease-in-out cursor-pointer' ,
177
213
currentIndex == i && '!opacity-100' ,
178
214
) }
179
215
key = { i }
0 commit comments