|
1 | 1 | import Image from 'next/image'; |
2 | 2 | import { Swiper, SwiperSlide } from 'swiper/react'; |
3 | 3 | import { Navigation, Pagination } from 'swiper/modules'; |
| 4 | +import { useState } from 'react'; |
4 | 5 |
|
5 | 6 | function ImageSlide({ imageUrls }: { imageUrls: string[] }) { |
| 7 | + const shouldLoop = imageUrls.length > 1; |
| 8 | + const [loadedImages, setLoadedImages] = useState<Set<string>>(new Set()); |
| 9 | + |
| 10 | + const handleImageLoad = (imgUrl: string) => { |
| 11 | + setLoadedImages((prev) => new Set(prev).add(imgUrl)); |
| 12 | + }; |
| 13 | + |
6 | 14 | return ( |
7 | 15 | <Swiper |
8 | 16 | spaceBetween={20} |
9 | 17 | modules={[Navigation, Pagination]} |
10 | | - navigation |
| 18 | + navigation={shouldLoop} |
11 | 19 | pagination={{ clickable: true, type: 'bullets' }} |
12 | | - loop |
| 20 | + loop={shouldLoop} |
13 | 21 | className="w-full max-h-100 flex justify-center items-center" |
14 | 22 | > |
15 | 23 | {imageUrls.length > 0 && |
16 | 24 | imageUrls.map((img) => ( |
17 | 25 | <SwiperSlide className="w-full flex justify-center items-center" key={img}> |
18 | | - <Image |
19 | | - src={img} |
20 | | - alt="이미지" |
21 | | - width={150} |
22 | | - height={150} |
23 | | - className="object-contain w-full max-h-[400px]" |
24 | | - /> |
| 26 | + <div className="relative w-full h-[400px] flex items-center justify-center"> |
| 27 | + {!loadedImages.has(img) && ( |
| 28 | + <div className="absolute inset-0 flex items-center justify-center bg-gray/80 rounded-lg"> |
| 29 | + <div className="w-8 h-8 border-4 border-secondary border-t-tertiary rounded-full animate-spin"></div> |
| 30 | + </div> |
| 31 | + )} |
| 32 | + <Image |
| 33 | + src={img} |
| 34 | + alt="이미지" |
| 35 | + width={800} |
| 36 | + height={600} |
| 37 | + quality={90} |
| 38 | + priority |
| 39 | + onLoad={() => handleImageLoad(img)} |
| 40 | + onError={() => handleImageLoad(img)} |
| 41 | + className={`object-contain w-full max-h-[400px] transition-opacity duration-300 ${ |
| 42 | + loadedImages.has(img) ? 'opacity-100' : 'opacity-0' |
| 43 | + }`} |
| 44 | + style={{ width: 'auto', height: 'auto' }} |
| 45 | + /> |
| 46 | + </div> |
25 | 47 | </SwiperSlide> |
26 | 48 | ))} |
27 | 49 | </Swiper> |
|
0 commit comments