93 lines
2.4 KiB
TypeScript
93 lines
2.4 KiB
TypeScript
// ... existing code ...
|
|
import React, { useRef, useState, useEffect } from 'react';
|
|
import Autoplay from 'embla-carousel-autoplay';
|
|
import { Carousel, CarouselContent, CarouselItem, type CarouselApi } from '@repo/ui/components/carousel';
|
|
|
|
const CarouselDemo: React.FC = () => {
|
|
const [carouselAPI, setCarouselAPI] = useState<CarouselApi | null>(null);
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
const plugin = useRef(Autoplay({ delay: 2000, stopOnInteraction: true }));
|
|
|
|
// 轮播图数据
|
|
const slides = [
|
|
{
|
|
id: 1,
|
|
image: '/header.png',
|
|
content: '两会闭幕 从春天出发',
|
|
},
|
|
{
|
|
id: 2,
|
|
image: '/header.png',
|
|
content: '习近平主席重要讲话',
|
|
},
|
|
{
|
|
id: 3,
|
|
image: '/header.png',
|
|
content: '全国人大代表步出人民大会堂',
|
|
},
|
|
];
|
|
|
|
// 监听轮播图变化
|
|
useEffect(() => {
|
|
if (!carouselAPI) return;
|
|
|
|
const updateCurrentIndex = () => {
|
|
setCurrentIndex(carouselAPI.selectedScrollSnap());
|
|
};
|
|
|
|
carouselAPI.on('select', updateCurrentIndex);
|
|
|
|
return () => {
|
|
carouselAPI.off('select', updateCurrentIndex);
|
|
};
|
|
}, [carouselAPI]);
|
|
|
|
// 滚动到指定索引
|
|
const scrollToIndex = (index: number) => {
|
|
if (carouselAPI) {
|
|
carouselAPI.scrollTo(index);
|
|
setCurrentIndex(index);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="relative w-full h-full">
|
|
<Carousel
|
|
className="h-full w-full"
|
|
setApi={setCarouselAPI}
|
|
plugins={[plugin.current, Autoplay({ delay: 2000, stopOnInteraction: true })]}
|
|
onMouseEnter={plugin.current.stop}
|
|
onMouseLeave={plugin.current.reset}
|
|
>
|
|
<CarouselContent className="h-[540px]">
|
|
{slides.map((slide) => (
|
|
<CarouselItem key={slide.id}>
|
|
<div className="h-full w-full relative">
|
|
<img
|
|
src={slide.image}
|
|
alt={slide.content}
|
|
className="w-full h-full object-cover"
|
|
style={{ objectFit: 'fill', backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat' }}
|
|
/>
|
|
</div>
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
</Carousel>
|
|
|
|
{/* 圆点指示器 */}
|
|
<div className="absolute bottom-5 right-5 flex justify-center space-x-2 ">
|
|
{slides.map((_, index) => (
|
|
<button
|
|
key={index}
|
|
className={`w-8 h-1 rounded-full mx-1 ${currentIndex === index ? 'bg-white' : 'bg-white opacity-50'}`}
|
|
onClick={() => scrollToIndex(index)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CarouselDemo;
|