// 引入 React 核心库 import * as React from "react"; // 引入 Embla Carousel 的自动播放插件 import Autoplay from "embla-carousel-autoplay"; // 引入自定义 UI 组件:Card 和 CardContent(通常用于内容容器) import { Card, CardContent } from "@/ui/card"; // 引入自定义轮播组件及其子组件和类型定义 import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselApi, // Embla 轮播实例的类型定义 } from "@/ui/carousel"; // 定义轮播图使用的图片资源路径数组 const imageUrls = [ "/images/carousel-1.jpg", "/images/carousel-2.jpg", "/images/carousel-3.jpg", "/images/carousel-4.jpg", "/images/carousel-5.jpg", "/images/carousel-6.jpg", ]; // 定义组件接收的 props 接口,提供类型安全 export interface CarouselDemoProps { // 分页指示器位置:'left' 表示左下角,'right' 表示右下角,默认为 'right' paginationPosition?: 'left' | 'right'; // 分页指示器样式:'dot' 为圆形小点,'bar' 为横向小条,默认为 'dot' paginationStyle?: 'dot' | 'bar'; } // 导出 CarouselDemo 组件,接收两个可选 props,并设置默认值 export function CarouselDemo({ paginationPosition = 'right', // 默认右下角 paginationStyle = 'dot', // 默认圆形指示器 }: CarouselDemoProps) { // 存储 Embla 轮播实例的引用,用于控制滚动等操作 const [api, setApi] = React.useState(); // 当前激活的幻灯片索引(从 0 开始) const [current, setCurrent] = React.useState(0); // 总共的幻灯片数量(由 Embla API 动态获取) const [count, setCount] = React.useState(0); // 图片总数(用于渲染轮播项) const totalSlides = imageUrls.length; // 副作用:监听 api 变化,初始化轮播状态并绑定 select 事件 React.useEffect(() => { if (!api) return; // 如果 api 尚未就绪,直接返回 // 获取所有 snap 点的数量(即幻灯片总数) setCount(api.scrollSnapList().length); // 设置当前选中的 snap 索引 setCurrent(api.selectedScrollSnap()); // 监听轮播切换事件(用户手动滑动或自动播放时触发) api.on("select", () => { setCurrent(api.selectedScrollSnap()); // 更新当前激活项 }); }, [api]); // 仅当 api 发生变化时重新执行 // 渲染组件 return ( // 外层容器:相对定位,占满父容器宽高
{/* 轮播主容器 */} {/* 轮播内容区域 */} {/* 遍历图片数组,为每张图创建一个轮播项 */} {imageUrls.map((src, index) => ( {/* 内部包裹层:无内边距,占满 */}
{/* 使用 CardContent 包裹图片,移除默认间距 */} {/* 图片元素:自动填充容器,保持比例裁剪 */}
{/* 可选:设置固定宽高比 */} {`Slide
))}
{/* 上一张按钮(左箭头) */} {/* */} {/* 下一张按钮(右箭头) */} {/* */}
{/* 分页指示器容器:绝对定位在底部 */}
{/* 动态生成指示器按钮 */} {Array.from({ length: count }).map((_, index) => (
); }