Skip to Content
@anker-in/headless-ui 2.0 is released 🎉

ThreeDCarousel (轮播)

加载中...
当前视口: 1920px × 600px场景: 浅色主题 3D 轮播
打开链接

功能特性

ThreeDCarousel 是一个功能强大的3D轮播组件,提供桌面端3D视觉效果和移动端流畅滑动体验:

核心特性

  • 3D 视觉效果 - 桌面端使用 Swiper Coverflow 效果,提供立体视觉体验
  • 响应式双模式 - 桌面端 3D 效果,移动端卡片滑动,自动适配
  • 无限循环播放 - 支持循环滑动浏览,小于 4 项自动克隆
  • 自定义导航 - 自定义 SVG 箭头,支持 hover 效果
  • 响应式图片 - 桌面/移动端独立图片资源,自动降级
  • 主题支持 - 单项主题切换(明暗模式)
  • 智能内容展示 - 桌面端仅激活项显示内容,避免视觉干扰
  • 图片滤镜效果 - 非激活项自动应用暗化滤镜
  • 曝光追踪 - 集成 useExposure 自动追踪组件可见性
  • 语义化类名 - BEM 命名规范,方便样式定制
  • Ref 转发 - 支持 forwardRef 和 useImperativeHandle
  • 可访问性 - 导航按钮包含 aria-label

Props参数

ThreeDCarouselProps

Prop类型默认值必需说明
dataThreeDCarouselData-组件业务数据,包含标题和轮播项列表
classNamestring--自定义样式类名,应用于根容器
refReact.Ref<HTMLDivElement>--Ref 转发,指向根容器 DOM 元素

ThreeDCarouselData

字段类型默认值必需说明
titlestring-组件标题,支持 HTML 内容
itemsThreeDCarouselItem[][]轮播项列表,建议 3-6 项

ThreeDCarouselItem

字段类型默认值必需说明
imageUrlMedia | null-桌面端图片资源,推荐尺寸 1648x960 (1.72:1)
mobImageUrlMedia | null-移动端图片资源,推荐尺寸 592x720 (0.82:1),为 null 时降级使用 imageUrl
titlestring-项目标题,支持 HTML 内容
descriptionstring-项目描述,支持 HTML 内容
buttonTextstring--按钮文本,为空时不显示按钮
buttonLinkstring | null--按钮跳转链接
theme'light' | 'dark''light'-项目主题,影响文本颜色

Media

字段类型必需说明
urlstring图片 URL 地址
altstring图片替代文本(无障碍)
thumbnailURLstring-缩略图 URL
mimeTypestring-MIME 类型,如 ‘image/png’
widthnumber-图片宽度(像素)
heightnumber-图片高度(像素)

类型定义

import type { Media, Theme } from '../../types/props' export interface ThreeDCarouselItem { /** 主题 */ theme?: Theme /** 桌面端图片 */ imageUrl: Media | null /** 移动端图片 */ mobImageUrl: Media | null /** 标题 */ title: string /** 描述 */ description: string /** 按钮文本 */ buttonText?: string /** 按钮链接 */ buttonLink?: string | null } export interface ThreeDCarouselProps { data: { title: string /** 轮播项列表 */ items: ThreeDCarouselItem[] } /** 自定义类名 */ className?: string }

使用示例

示例 1: 基础三项轮播

展示最基本的3项轮播配置:

import { ThreeDCarousel } from '@anker-in/headless-ui/biz' <ThreeDCarousel data={{ title: 'Product Features', items: [ { imageUrl: { url: '/feature1-desktop.jpg', alt: 'Feature 1' }, mobImageUrl: { url: '/feature1-mobile.jpg', alt: 'Feature 1' }, title: 'Advanced Technology', description: 'Cutting-edge innovation for superior performance', buttonText: 'Learn More', buttonLink: '/features/technology', }, { imageUrl: { url: '/feature2-desktop.jpg', alt: 'Feature 2' }, mobImageUrl: { url: '/feature2-mobile.jpg', alt: 'Feature 2' }, title: 'User-Friendly Design', description: 'Intuitive interface for effortless control', buttonText: 'Explore', buttonLink: '/features/design', }, { imageUrl: { url: '/feature3-desktop.jpg', alt: 'Feature 3' }, mobImageUrl: { url: '/feature3-mobile.jpg', alt: 'Feature 3' }, title: 'Premium Quality', description: 'Built to last with superior materials', buttonText: 'Shop Now', buttonLink: '/shop', }, ], }} />

示例 2: 暗色主题轮播项

使用暗色主题展示深色背景场景:

<ThreeDCarousel data={{ title: 'Midnight Collection', items: [ { theme: 'dark', // 使用暗色主题 imageUrl: { url: '/night-scene1.jpg', alt: 'Night Scene 1' }, mobImageUrl: { url: '/night-scene1-mobile.jpg', alt: 'Night Scene 1' }, title: 'Night Vision', description: 'See clearly in complete darkness', buttonText: 'Discover', buttonLink: '/features/night-vision', }, { theme: 'dark', imageUrl: { url: '/night-scene2.jpg', alt: 'Night Scene 2' }, mobImageUrl: { url: '/night-scene2-mobile.jpg', alt: 'Night Scene 2' }, title: 'Silent Operation', description: 'Whisper-quiet performance', buttonText: 'Learn More', buttonLink: '/features/silent', }, ], }} />

示例 3: 无按钮轮播

不显示按钮,纯展示型轮播:

<ThreeDCarousel data={{ title: 'Visual Gallery', items: [ { imageUrl: { url: '/gallery1.jpg', alt: 'Gallery Image 1' }, mobImageUrl: { url: '/gallery1-mobile.jpg', alt: 'Gallery Image 1' }, title: 'Mountain Landscape', description: 'Breathtaking views from the summit', // 不提供 buttonText,按钮不显示 }, { imageUrl: { url: '/gallery2.jpg', alt: 'Gallery Image 2' }, mobImageUrl: { url: '/gallery2-mobile.jpg', alt: 'Gallery Image 2' }, title: 'Ocean Sunset', description: 'Golden hour by the sea', }, { imageUrl: { url: '/gallery3.jpg', alt: 'Gallery Image 3' }, mobImageUrl: { url: '/gallery3-mobile.jpg', alt: 'Gallery Image 3' }, title: 'Forest Trail', description: 'Explore the wilderness', }, ], }} />

示例 4: 移动端图片降级

未提供移动端图片时,自动使用桌面端图片:

<ThreeDCarousel data={{ title: 'Quick Setup', items: [ { imageUrl: { url: '/setup-desktop.jpg', alt: 'Setup Guide' }, mobImageUrl: null, // 移动端自动使用 imageUrl title: 'Easy Installation', description: 'Get started in minutes', buttonText: 'Start', buttonLink: '/setup', }, ], }} />

示例 5: 自定义样式

使用自定义className添加渐变背景:

<ThreeDCarousel data={{ title: 'Premium Experience', items: [ { imageUrl: { url: '/premium1.jpg', alt: 'Premium 1' }, mobImageUrl: { url: '/premium1-mobile.jpg', alt: 'Premium 1' }, title: 'Luxury Design', description: 'Elegance meets functionality', buttonText: 'Explore', buttonLink: '/premium', }, ], }} className="bg-gradient-to-b from-slate-900 to-slate-800 py-20" />

自定义导航按钮样式:

/* 导航按钮渐变色 */ .three-d-carousel__nav-icon { color: #667eea; transition: all 0.3s ease; } .three-d-carousel__nav-icon:hover { color: #764ba2; transform: scale(1.1); } /* 导航按钮圆圈背景 */ .three-d-carousel__nav-button { opacity: 0.8; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1)); } .three-d-carousel__nav-button:hover { opacity: 1; }

示例 6: HTML 富文本标题

标题和描述支持HTML内容:

<ThreeDCarousel data={{ title: 'Experience <span class="text-blue-400">Revolutionary</span> Technology', items: [ { imageUrl: { url: '/tech1.jpg', alt: 'Technology 1' }, mobImageUrl: { url: '/tech1-mobile.jpg', alt: 'Technology 1' }, title: '<strong>AI-Powered</strong> Intelligence', description: 'Smart features that <em>adapt</em> to your needs', buttonText: 'Learn More', buttonLink: '/ai', }, ], }} />

示例 7: 单项轮播(测试场景)

单个项目展示,组件会自动克隆以确保循环效果:

<ThreeDCarousel data={{ title: 'Hero Product', items: [ { imageUrl: { url: '/hero-desktop.jpg', alt: 'Hero Product' }, mobImageUrl: { url: '/hero-mobile.jpg', alt: 'Hero Product' }, title: 'Our Flagship Model', description: 'The ultimate solution for your needs', buttonText: 'Shop Now', buttonLink: '/shop/flagship', }, ], }} />

说明: 小于 4 项时,组件会自动克隆项目以确保循环效果流畅。

示例 8: 六项轮播(完整效果)

展示完整的产品线:

<ThreeDCarousel data={{ title: 'Complete Product Line', items: [ { imageUrl: { url: '/product1-desktop.jpg', alt: 'Product 1' }, mobImageUrl: { url: '/product1-mobile.jpg', alt: 'Product 1' }, title: 'Model A', description: 'Entry-level performance', buttonText: 'View Details', buttonLink: '/products/a', }, { imageUrl: { url: '/product2-desktop.jpg', alt: 'Product 2' }, mobImageUrl: { url: '/product2-mobile.jpg', alt: 'Product 2' }, title: 'Model B', description: 'Balanced features and price', buttonText: 'View Details', buttonLink: '/products/b', }, { imageUrl: { url: '/product3-desktop.jpg', alt: 'Product 3' }, mobImageUrl: { url: '/product3-mobile.jpg', alt: 'Product 3' }, title: 'Model C', description: 'Advanced capabilities', buttonText: 'View Details', buttonLink: '/products/c', }, { imageUrl: { url: '/product4-desktop.jpg', alt: 'Product 4' }, mobImageUrl: { url: '/product4-mobile.jpg', alt: 'Product 4' }, title: 'Model D', description: 'Professional grade', buttonText: 'View Details', buttonLink: '/products/d', }, { imageUrl: { url: '/product5-desktop.jpg', alt: 'Product 5' }, mobImageUrl: { url: '/product5-mobile.jpg', alt: 'Product 5' }, title: 'Model E', description: 'Premium performance', buttonText: 'View Details', buttonLink: '/products/e', }, { imageUrl: { url: '/product6-desktop.jpg', alt: 'Product 6' }, mobImageUrl: { url: '/product6-mobile.jpg', alt: 'Product 6' }, title: 'Model F', description: 'Ultimate flagship', buttonText: 'View Details', buttonLink: '/products/f', }, ], }} />

示例 9: Ref 转发

使用 ref 进行滚动定位:

function CarouselWithRef() { const carouselRef = useRef<HTMLDivElement>(null) const scrollToCarousel = () => { carouselRef.current?.scrollIntoView({ behavior: 'smooth' }) } return ( <div> <button onClick={scrollToCarousel}>Go to Carousel</button> <ThreeDCarousel ref={carouselRef} data={{ title: 'Scroll Target', items: [ { imageUrl: { url: '/scroll-desktop.jpg', alt: 'Scroll Target' }, mobImageUrl: { url: '/scroll-mobile.jpg', alt: 'Scroll Target' }, title: 'Find Me', description: 'Click the button above to scroll here', buttonText: 'Got It', buttonLink: '#', }, ], }} /> </div> ) }

示例 10: 混合主题轮播

不同轮播项使用不同主题:

<ThreeDCarousel data={{ title: 'Day & Night', items: [ { theme: 'light', // 明亮主题 imageUrl: { url: '/day-scene.jpg', alt: 'Day Scene' }, mobImageUrl: { url: '/day-scene-mobile.jpg', alt: 'Day Scene' }, title: 'Daytime Performance', description: 'Optimized for bright environments', buttonText: 'Learn More', buttonLink: '/day', }, { theme: 'dark', // 暗色主题 imageUrl: { url: '/night-scene.jpg', alt: 'Night Scene' }, mobImageUrl: { url: '/night-scene-mobile.jpg', alt: 'Night Scene' }, title: 'Nighttime Excellence', description: 'Designed for low-light conditions', buttonText: 'Learn More', buttonLink: '/night', }, ], }} />

BEM类名结构

组件使用完整的BEM命名规范,便于样式定制:

根元素

  • .three-d-carousel - 组件根容器

标题区域

  • .three-d-carousel__title - 主标题

轮播区域

  • .three-d-carousel__swiper - Swiper 容器
  • .three-d-carousel__slide - 单个滑块
  • .three-d-carousel__image-wrapper - 图片外层容器
  • .three-d-carousel__image - 图片元素
  • .three-d-carousel__content - 内容容器
  • .three-d-carousel__item-title - 项目标题
  • .three-d-carousel__description - 项目描述
  • .three-d-carousel__button - 按钮

导航区域

  • .three-d-carousel__navigation - 导航容器
  • .three-d-carousel__nav-button - 导航按钮
  • .three-d-carousel__nav-button--prev - 上一页按钮
  • .three-d-carousel__nav-button--next - 下一页按钮
  • .three-d-carousel__nav-icon - 导航图标

响应式行为

断点说明

组件在不同断点下的行为变化:

断点范围Swiper 效果图片源内容显示导航按钮
Mobile0-767pxSlidemobImageUrl全部显示SVG箭头
Tablet768-1024pxCoverflowimageUrl仅激活项SVG箭头
Laptop+≥1025pxCoverflowimageUrl仅激活项SVG箭头

Swiper 配置切换

const isMobile = useMediaQuery({ query: '(max-width: 768px)' }) // 桌面端配置 { effect: 'coverflow', coverflowEffect: { rotate: 0, stretch: 0, depth: 300, modifier: 1, slideShadows: false, }, slidesPerView: 'auto', centeredSlides: true, } // 移动端配置 { effect: 'slide', slidesPerView: 1.2, spaceBetween: 16, centeredSlides: true, }

图片显示逻辑

// 桌面端显示 imageUrl <Picture source={isMobile ? item.mobImageUrl?.url : item.imageUrl?.url} alt={isMobile ? item.mobImageUrl?.alt : item.imageUrl?.alt} className="tablet:block hidden" // 桌面端显示 /> // 移动端显示 mobImageUrl (降级到 imageUrl) <Picture source={item.mobImageUrl?.url || item.imageUrl?.url} alt={item.mobImageUrl?.alt || item.imageUrl?.alt} className="tablet:hidden block" // 移动端显示 />

设计规范

使用建议

  1. 轮播项数量: 建议 3-6 项,过多会影响用户体验
  2. 图片尺寸:
    • 桌面端: 推荐 1648x960px (1.72:1 横向比例)
    • 移动端: 推荐 592x720px (0.82:1 竖向比例)
  3. 标题长度: 建议 8-20 个字符
  4. 描述长度: 建议 30-80 个字符
  5. 按钮文本: 建议 4-12 个字符

最佳实践

  • 提供移动端图片: 优化移动端加载速度和显示效果
  • 使用WebP格式: 减小图片文件大小
  • 设置合适比例: 桌面横向,移动竖向
  • 控制项目数量: 3-6 项为最佳
  • 避免过大图片: 单张图片不超过 500KB
  • 避免复杂背景: 影响文本可读性

图片优化建议

# 使用 ImageMagick 优化图片 # 桌面端图片 convert input.jpg -resize 1648x960^ -gravity center -extent 1648x960 -quality 85 desktop.jpg # 移动端图片 convert input.jpg -resize 592x720^ -gravity center -extent 592x720 -quality 85 mobile.jpg

无障碍性

ARIA 标签

<section role="region" aria-label={title} data-ui-component-id="ThreeDCarousel" > <Heading as="h2" html={title} /> <div role="group" aria-roledescription="carousel【✅ 已发布】" > {items.map((item, index) => ( <div role="group" aria-roledescription="slide" aria-label={`Slide ${index + 1} of ${items.length}`} > <Picture source={item.imageUrl?.url} alt={item.imageUrl?.alt} /> </div> ))} </div> <button aria-label="Previous slide" className="three-d-carousel__nav-button--prev" > <svg aria-hidden="true">...</svg> </button> <button aria-label="Next slide" className="three-d-carousel__nav-button--next" > <svg aria-hidden="true">...</svg> </button> </section>

键盘导航

操作
Tab在导航按钮之间切换焦点
Enter / Space激活当前按钮
Arrow Left上一张(推荐实现)
Arrow Right下一张(推荐实现)

性能优化

React优化

// 使用useMemo缓存数据处理 const processedItems = useMemo(() => { // 小于4项时自动克隆 if (items.length < 4) { return [...items, ...items, ...items, ...items] } return items }, [items]) // 使用React.memo包裹子组件 const CarouselSlide = React.memo(({ item }) => ( <div className="three-d-carousel__slide"> {/* 滑块内容 */} </div> ))

图片优化

// 图片懒加载 <Picture source={item.imageUrl?.url} alt={item.imageUrl?.alt} loading="lazy" /> // 响应式图片 <picture> <source media="(min-width: 768px)" srcSet={item.imageUrl?.url} /> <source media="(max-width: 767px)" srcSet={item.mobImageUrl?.url || item.imageUrl?.url} /> <img src={item.imageUrl?.url} alt={item.imageUrl?.alt} /> </picture>

Swiper优化

// 仅加载必要模块 import { Swiper, SwiperSlide } from 'swiper/react' import { EffectCoverflow, Navigation } from 'swiper/modules' // 优化配置 <Swiper modules={[EffectCoverflow, Navigation]} lazy={true} preloadImages={false} watchSlidesProgress={true} />

常见问题 FAQ

1. 如何自定义导航按钮样式?

: 使用CSS覆盖导航按钮类名:

.three-d-carousel__nav-icon { color: #667eea; } .three-d-carousel__nav-button { background: rgba(255, 255, 255, 0.9); border-radius: 50%; }

2. 为什么小于4项时会重复显示?

: 为了确保Coverflow效果流畅,组件会自动克隆项目。这是Swiper Coverflow效果的要求,至少需要4个滑块才能正常工作。

3. 移动端图片降级是如何工作的?

: 当 mobImageUrl 为 null 时,组件会自动使用 imageUrl:

<Picture source={item.mobImageUrl?.url || item.imageUrl?.url} alt={item.mobImageUrl?.alt || item.imageUrl?.alt} />

4. 如何实现无限循环?

: Swiper 配置中设置 loop: true:

<Swiper loop={true} loopedSlides={items.length} />

5. 桌面端为什么只显示激活项内容?

: 为了避免视觉干扰,桌面端3D效果下仅显示中心激活项的标题、描述和按钮。移动端则显示所有项目内容。

6. 如何自定义Coverflow效果参数?

: 修改源码中的 coverflowEffect 配置:

coverflowEffect: { rotate: 0, // 旋转角度 stretch: 0, // 拉伸距离 depth: 300, // 深度(越大越明显) modifier: 1, // 修饰符 slideShadows: false, }

7. 如何禁用自动播放?

: 组件默认不自动播放。如需自动播放,可在Swiper配置中添加:

<Swiper autoplay={{ delay: 3000, disableOnInteraction: false, }} />

8. 图片滤镜效果如何自定义?

: 非激活项使用 CSS filter,可通过CSS覆盖:

.swiper-slide:not(.swiper-slide-active) .three-d-carousel__image { filter: brightness(0.7) contrast(0.9); }

9. 如何获取当前激活的滑块索引?

: 使用Swiper的 onSlideChange 回调:

<Swiper onSlideChange={(swiper) => { console.log('当前索引:', swiper.activeIndex) }} />

10. 支持触摸滑动吗?

: 是的,Swiper默认支持触摸滑动。可通过配置调整:

<Swiper touchRatio={1} threshold={5} simulateTouch={true} />

相关资源

设计资源

代码资源

  • 源代码: packages/ui/src/biz-components/ThreeDCarousel/
  • 类型定义: packages/ui/src/biz-components/ThreeDCarousel/types.ts
  • Story 文件: packages/ui/src/stories/threeDCarousel.stories.tsx
  • 单元测试: packages/ui/tests/ThreeDCarousel.test.tsx

依赖组件

  • Heading - 标题组件 (@anker-in/headless-ui)
  • Text - 文本组件 (@anker-in/headless-ui)
  • Picture - 图片组件 (@anker-in/headless-ui)
  • Button - 按钮组件 (@anker-in/headless-ui)

外部依赖

  • swiper - 轮播库 (v11.0+)
  • react-responsive - 响应式判断 (v9.0+)

相关文档


Changelog

v1.0.0 (2026-01-16)

首次发布

  • ✅ 3D Coverflow 视觉效果(桌面端)
  • ✅ 响应式双模式(桌面3D/移动滑动)
  • ✅ 无限循环播放
  • ✅ 自定义SVG导航箭头
  • ✅ 响应式图片(桌面/移动端独立)
  • ✅ 主题支持(light/dark)
  • ✅ 智能内容展示(桌面端仅激活项)
  • ✅ 图片滤镜效果(非激活项暗化)
  • ✅ 曝光追踪集成
  • ✅ BEM命名规范
  • ✅ Ref转发支持
  • ✅ ARIA无障碍标签

已知问题:

  • 小于4项时会自动克隆,可能导致key重复警告(已处理)

待优化项:

  • 支持自定义Coverflow参数
  • 支持自动播放配置
  • 支持分页指示器(pagination) EOFMDX
Last updated on