news/app/components/AutoCarousel.tsx

95 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 引入 Embla Carousel 的自动播放插件
import Autoplay from "embla-carousel-autoplay";
// 引入自定义 UI 组件Card 和 CardContent通常用于内容容器
import { Card, CardContent } from "@/ui/card";
// 引入自定义轮播组件及其子组件和类型定义
import {
Carousel,
CarouselContent,
CarouselItem,
type CarouselApi, // Embla 轮播实例的类型定义
} from "@/ui/carousel";
import * as React from "react";
// 定义轮播图中要展示的图片资源路径数组
// 包含轮播主图carousel-*.jpg以及额外的静态资源如 book1.png、header.png 等)
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",
"/images/book1.png", // 可能是书籍封面
"/images/header.png", // 可能是顶部 Banner 图
"/images/jcdt.png", // 可能是“基层动态”等模块图标
];
// 导出名为 AutoCarouselDemo 的函数式组件
export function AutoCarouselDemo() {
const [api, setApi] = React.useState<CarouselApi>();
const [selectedIndex, setSelectedIndex] = React.useState(0);
const [current, setCurrent] = React.useState(0);
React.useEffect(() => {
if (!api) return;
setCurrent(api.selectedScrollSnap());
api.on("select", () => {
setCurrent(api.selectedScrollSnap());
});
}, [api]);
return (
// 外层容器相对定位水平居中上下留有足够间距mt-30 ≈ 120px, mb-20 ≈ 80px
<div className="relative w-full mx-auto mt-30 mb-20">
{/* 轮播主组件 */}
<Carousel
opts={{
loop: true, // 启用无限循环:最后一张后自动回到第一张
align: "start", // 对齐方式设为“起始对齐”,确保首项紧贴左侧(适用于非全屏单图场景)
}}
plugins={[
// 配置自动播放插件:
Autoplay({
delay: 3000, // 每 3 秒自动切换一次
stopOnInteraction: false, // 用户点击或拖拽后不停止自动播放(持续轮播)
}),
]}
className="w-full" // 轮播容器占满父级宽度
>
{/* 轮播内容区域:添加 gap-4 实现卡片间 1rem16px间距 */}
<CarouselContent className="flex gap-16 h-full ">
{/* 遍历所有图片 URL为每张图生成一个轮播项 */}
{imageUrls.map((src, index) => (
<CarouselItem
key={index}
// 响应式宽度控制
// - 默认小屏每个项占 1/4 宽度basis-1/4中屏md 1/3
// - 中屏md 1/3
// - 大屏lg回到 1/4适合展示 4
className="basis-1/4 md:basis-1/3 lg:basis-1/4 flex-shrink-0 relative "
>
{/* 卡片外层:添加内边距、悬停缩放动效、鼠标指针样式 */}
<div className="p-1 transition-transform duration-500 cursor-pointer">
{/* 图片容器:固定高度 h-120即 30rem = 480px隐藏溢出内容 */}
<div className="overflow-hidden border-none h-120">
{/* 使用 CardContent 包裹图片,确保与 UI 系统一致 */}
<CardContent className="relative w-full h-full p-0 "> {/* p-0 移除默认内边距 */}
{/* 实际图片元素 */}
<img
src={src}
alt={`Slide ${index + 1}`} // 无障碍访问描述当前幻灯片
className="w-full h-full object-cover hover:scale-105 transition-transform duration-500" // 宽高填满容器保持比例裁剪
loading="lazy" // 懒加载提升页面初始加载性能
/>
</CardContent>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
</div>
);
}