加载中...
当前视口: 1920px × 600px场景: 浅色主题 3D 轮播
打开链接功能特性
ThreeDCarousel 是一个功能强大的3D轮播组件,提供桌面端3D视觉效果和移动端流畅滑动体验:
核心特性
- ✅ 3D 视觉效果 - 桌面端使用 Swiper Coverflow 效果,提供立体视觉体验
- ✅ 响应式双模式 - 桌面端 3D 效果,移动端卡片滑动,自动适配
- ✅ 无限循环播放 - 支持循环滑动浏览,小于 4 项自动克隆
- ✅ 自定义导航 - 自定义 SVG 箭头,支持 hover 效果
- ✅ 响应式图片 - 桌面/移动端独立图片资源,自动降级
- ✅ 主题支持 - 单项主题切换(明暗模式)
- ✅ 智能内容展示 - 桌面端仅激活项显示内容,避免视觉干扰
- ✅ 图片滤镜效果 - 非激活项自动应用暗化滤镜
- ✅ 曝光追踪 - 集成 useExposure 自动追踪组件可见性
- ✅ 语义化类名 - BEM 命名规范,方便样式定制
- ✅ Ref 转发 - 支持 forwardRef 和 useImperativeHandle
- ✅ 可访问性 - 导航按钮包含 aria-label
Props参数
ThreeDCarouselProps
| Prop | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
data | ThreeDCarouselData | - | ✅ | 组件业务数据,包含标题和轮播项列表 |
className | string | - | - | 自定义样式类名,应用于根容器 |
ref | React.Ref<HTMLDivElement> | - | - | Ref 转发,指向根容器 DOM 元素 |
ThreeDCarouselData
| 字段 | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
title | string | - | ✅ | 组件标题,支持 HTML 内容 |
items | ThreeDCarouselItem[] | [] | ✅ | 轮播项列表,建议 3-6 项 |
ThreeDCarouselItem
| 字段 | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
imageUrl | Media | null | - | ✅ | 桌面端图片资源,推荐尺寸 1648x960 (1.72:1) |
mobImageUrl | Media | null | - | ✅ | 移动端图片资源,推荐尺寸 592x720 (0.82:1),为 null 时降级使用 imageUrl |
title | string | - | ✅ | 项目标题,支持 HTML 内容 |
description | string | - | ✅ | 项目描述,支持 HTML 内容 |
buttonText | string | - | - | 按钮文本,为空时不显示按钮 |
buttonLink | string | null | - | - | 按钮跳转链接 |
theme | 'light' | 'dark' | 'light' | - | 项目主题,影响文本颜色 |
Media
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
url | string | ✅ | 图片 URL 地址 |
alt | string | ✅ | 图片替代文本(无障碍) |
thumbnailURL | string | - | 缩略图 URL |
mimeType | string | - | MIME 类型,如 ‘image/png’ |
width | number | - | 图片宽度(像素) |
height | number | - | 图片高度(像素) |
类型定义
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 效果 | 图片源 | 内容显示 | 导航按钮 |
|---|---|---|---|---|---|
| Mobile | 0-767px | Slide | mobImageUrl | 全部显示 | SVG箭头 |
| Tablet | 768-1024px | Coverflow | imageUrl | 仅激活项 | SVG箭头 |
| Laptop+ | ≥1025px | Coverflow | imageUrl | 仅激活项 | 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" // 移动端显示
/>设计规范
使用建议
- 轮播项数量: 建议 3-6 项,过多会影响用户体验
- 图片尺寸:
- 桌面端: 推荐 1648x960px (1.72:1 横向比例)
- 移动端: 推荐 592x720px (0.82:1 竖向比例)
- 标题长度: 建议 8-20 个字符
- 描述长度: 建议 30-80 个字符
- 按钮文本: 建议 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}
/>相关资源
设计资源
- Figma 设计稿: IPC-To-C-Design-System
- Design Token 文档: https://headless-ui-doc.netlify.app/
代码资源
- 源代码:
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