Files
AtomUI/docs/Desktop.Controls/Carousel/Carousel.md
T

11 KiB
Raw Blame History

Carousel 走马灯

概述

走马灯(Carousel)是循环展示组件,用于在有限空间内循环播放一组内容(图片、卡片等)。支持自动播放、分页指示器、导航按钮、滑动手势、多种过渡效果和四个方向的分页位置。

AtomUI 的 Carousel 控件复刻了 Ant Design 5.0 Carousel 的设计规范,在 .NET / Avalonia 平台上提供与 Ant Design React 版一致的视觉体验和交互行为。


设计原理

Ant Design 的走马灯设计哲学

Ant Design 对走马灯的定位是:「在有限空间内,循环播放同一类型的图片、文字等内容」。典型使用场景包括:

场景 说明
🖼️ 首页横幅 多张 Banner 图片轮播展示
📦 产品展示 产品多角度图片切换
📰 新闻轮播 新闻标题自动滚动
🎯 引导页 新用户引导步骤展示

核心能力:

能力 设计意图
🔄 自动播放 内容定时自动切换,无需用户操作
📍 分页指示器 显示当前位置和总页数,支持点击跳转
⬅️➡️ 导航箭头 前进/后退按钮,提供手动翻页
🔁 无限循环 到达末尾后自动回到开头,形成循环
🎞️ 过渡效果 滑动(Scroll)和淡入淡出(Fade)两种切换方式
⏱️ 进度展示 指示器上展示自动播放的进度

Avalonia SelectingItemsControl 基础能力

AtomUI 的 Carousel 继承自 Avalonia 框架的 SelectingItemsControl。其继承链为:

Control → TemplatedControl → ItemsControl → SelectingItemsControl

SelectingItemsControl 提供了选中项管理(SelectedIndex / SelectedItem)、选择模式(SelectionMode)等基础能力。Carousel 将其用于管理「当前页」的概念——每个页面就是一个选中项。

AtomUI 的扩展设计

AtomUI Carousel 在 SelectingItemsControl 的基础上,遵循 Ant Design 5.0 规范做了以下扩展:

扩展能力 实现方式 设计动机
自动播放 IsAutoPlay + AutoPlaySpeed + DispatcherTimer 内容定时自动切换
分页指示器 CarouselPagination + CarouselPageIndicator 当前页位置可视化 + 点击跳转
导航箭头 CarouselNavButton + IsShowNavButtons 手动前进/后退翻页
无限循环 IsInfinite 到达末尾自动回到开头
过渡效果 CarouselTransitionEffect (Scroll / Fade) 滑动或淡入淡出
四方向分页 CarouselPaginationPosition (Top / Bottom / Left / Right) 指示器位置灵活配置
进度展示 IsShowTransitionProgress + 进度动画 指示器上展示自动播放进度条
滑动手势 IsSwipeEnabled + 指针手势检测 鼠标/触摸滑动切换页面
虚拟化面板 VirtualizingCarouselPanel 仅实例化当前页和过渡页,节省资源
Design Token CarouselToken + RegisterTokenResourceScope 视觉值从 Token 派生

功能详解

自动播放(IsAutoPlay)

当 IsAutoPlay = true 时:

  1. 创建 DispatcherTimer,间隔为 AutoPlaySpeed(默认 3 秒)
  2. 每次触发自动调用 Next() 切换到下一页
  3. 手动切换页面时(SelectedIndex 变化),定时器重新计时
  4. 控件从可视树分离时自动停止,重新附加时自动恢复

分页指示器

分页指示器由 CarouselPagination(内部 SelectingItemsControl)和 CarouselPageIndicator(单个指示点)组成:

  • 指示点默认为条形(宽 IndicatorWidth,高 IndicatorHeight)
  • 选中的指示点自动变宽为 IndicatorActiveWidth
  • 悬浮时不透明度从 0.2 变为 0.75
  • 点击指示点可跳转到对应页面
  • 通过 IsShowPagination 控制显示/隐藏

导航箭头(IsShowNavButtons)

当 IsShowNavButtons = true 时显示前进/后退按钮:

  • 使用 CarouselNavButton(继承 IconButton)
  • 图标为 LeftOutlined / RightOutlined
  • 默认不透明度 0.2,悬浮时变为 1.0
  • 非无限循环模式下,到达边界时自动隐藏对应按钮
  • 横向模式时按钮位于左右两侧,纵向模式时按钮位于上下两侧

分页位置(PaginationPosition)

分页指示器和导航箭头的位置随 PaginationPosition 变化:

位置 指示器位置 导航按钮位置 滑动方向 PageSlide 方向
Bottom(默认) 底部居中 左右两侧 水平 Horizontal
Top 顶部居中 左右两侧 水平 Horizontal
Left 左侧居中(旋转 90°) 上下两侧 垂直 Vertical
Right 右侧居中(旋转 90°) 上下两侧 垂直 Vertical

过渡效果(TransitionEffect)

效果 实现 说明
Scroll(默认) PageSlide 页面滑动切换,方向跟随 PaginationPosition
Fade CrossFade 淡入淡出切换

过渡动画参数通过 PageTransitionDuration、PageInEasing、PageOutEasing 配置。

进度展示(IsShowTransitionProgress)

当 IsAutoPlay = true 且 IsShowTransitionProgress = true 时:

  • 选中的指示点上显示进度条动画
  • 进度条从左到右填充,周期与 AutoPlaySpeed 一致
  • 悬浮指示点时进度条隐藏

滑动手势(IsSwipeEnabled)

当 IsSwipeEnabled = true 时:

  • 鼠标/触摸按下并拖动超过 30px 阈值即触发页面切换
  • 水平模式下左滑 = Next,右滑 = Previous
  • 垂直模式下上滑 = Next,下滑 = Previous
  • 导航按钮和分页指示器区域不触发滑动

虚拟化面板

VirtualizingCarouselPanel 实现 ILogicalScrollable,仅实例化当前页面和过渡中的页面,未显示的页面被回收到对象池,大幅减少内存占用。


与 Ant Design 规范的对齐程度

特性 Ant Design (React) AtomUI (Avalonia) 对齐情况
基本走马灯 ✅ <Carousel> ✅ <atom:Carousel> ✅ 完全对齐
自动播放 autoplay ✅ 布尔 ✅ IsAutoPlay ✅ 完全对齐
自动播放速度 autoplaySpeed ✅ 毫秒数 ✅ AutoPlaySpeed (TimeSpan) ✅ 完全对齐
分页位置 dotPosition ✅ top/bottom/left/right ✅ PaginationPosition 枚举 ✅ 完全对齐
淡入淡出 effect="fade" ✅ ✅ TransitionEffect="Fade" ✅ 完全对齐
箭头 arrows ✅ 5.17.0 新增 ✅ IsShowNavButtons ✅ 完全对齐
进度指示 dotProgress ✅ (未正式发布) ✅ IsShowTransitionProgress ✅ 完全对齐
无限循环 infinite ✅ ✅ IsInfinite ✅ 完全对齐
滑动手势 swipe ✅ (触屏) ✅ IsSwipeEnabled ✅ 扩展(鼠标+触摸)
beforeChange / afterChange ✅ 回调 ⚠️ 通过 SelectedIndex 变化监听 ⚠️ API 形式不同

继承关系

Avalonia.Controls.Primitives.TemplatedControl
  └── Avalonia.Controls.ItemsControl
        └── Avalonia.Controls.Primitives.SelectingItemsControl
              └── AtomUI.Desktop.Controls.Carousel
                    └── implements IMotionAwareControl

各层级职责划分:

层级 提供的能力
ItemsControl 子项管理、Items / ItemsSource 数据绑定、ItemTemplate 模板化
SelectingItemsControl 选中项管理(SelectedIndex / SelectedItem)、选择模式
AtomUI.Desktop.Controls.Carousel 自动播放、分页指示器、导航箭头、过渡效果、无限循环、滑动手势、虚拟化面板

实现的共享接口:

接口 定义位置 作用
IMotionAwareControl AtomUI.Controls.Shared 支持动画开关(IsMotionEnabled)

相关类型

类型 继承自 说明
CarouselPaginationPosition 枚举 分页位置:Top、Bottom、Left、Right
CarouselTransitionEffect 枚举 过渡效果:Scroll、Fade
CarouselPage ContentControl 走马灯页面容器
CarouselNavButton IconButton 导航箭头按钮
CarouselPageIndicator ContentControl(内部) 单个分页指示点
CarouselPagination SelectingItemsControl(内部) 分页指示器面板
VirtualizingCarouselPanel VirtualizingPanel(内部) 虚拟化面板,仅实例化当前页

源码位置

层级 文件路径 说明
控件类 src/AtomUI.Desktop.Controls/Carousel/Carousel.cs Carousel 主控件
枚举 src/AtomUI.Desktop.Controls/Carousel/CarouselEnums.cs 枚举定义
导航按钮 src/AtomUI.Desktop.Controls/Carousel/CarouselNavButton.cs 导航箭头按钮
页面容器 src/AtomUI.Desktop.Controls/Carousel/CarouselPage.cs CarouselPage 控件
指示点 src/AtomUI.Desktop.Controls/Carousel/CarouselPageIndicator.cs 分页指示点(内部)
分页面板 src/AtomUI.Desktop.Controls/Carousel/CarouselPagination.cs 分页指示器面板(内部)
虚拟化面板 src/AtomUI.Desktop.Controls/Carousel/VirtualizingCarouselPanel.cs 虚拟化面板(内部)
Token 定义 src/AtomUI.Desktop.Controls/Carousel/CarouselToken.cs 组件级 Design Token
主题模板 src/AtomUI.Desktop.Controls/Carousel/Themes/CarouselTheme.axaml ControlTheme AXAML
模板常量 src/AtomUI.Desktop.Controls/Carousel/Themes/CarouselPageThemeConstants.cs 模板部件名称常量
Gallery 示例 controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/CarouselShowCase.axaml 使用范例

模板结构

Carousel 的 ControlTemplate 采用分层 Panel 布局:

Panel
├── ScrollViewer#PART_ScrollViewer                       ← 滚动容器(隐藏滚动条)
│   └── ItemsPresenter#PART_ItemsPresenter               ← 页面展示(VirtualizingCarouselPanel)
├── CarouselNavButton#PART_PreviousButton                ← 前一页导航按钮(LeftOutlined)
├── CarouselNavButton#PART_NextButton                    ← 下一页导航按钮(RightOutlined)
└── LayoutTransformControl#PaginationLayoutTransform     ← 分页指示器布局(支持旋转)
    └── CarouselPagination#PART_Pagination               ← 分页指示器面板
        └── StackPanel (Horizontal, Spacing=IndicatorGap)
            └── CarouselPageIndicator × N                ← 每个页面一个指示点

分层设计理由:

  • 滚动容器独立:使用 ScrollViewer + VirtualizingCarouselPanel 实现虚拟化页面切换,隐藏原生滚动条。
  • 导航按钮浮动:按钮在 Panel 内浮动定位,根据 PaginationPosition 自动调整位置。
  • 分页指示器旋转:使用 LayoutTransformControl 包裹,左/右位置时旋转 90° 实现纵向指示器。

模板部件常量

常量名 值 说明
CarouselThemeConstants.ScrollViewerPart "PART_ScrollViewer" 滚动容器
CarouselThemeConstants.PaginationPart "PART_Pagination" 分页指示器面板
CarouselThemeConstants.PreviousButtonPart "PART_PreviousButton" 前一页按钮
CarouselThemeConstants.NextButtonPart "PART_NextButton" 下一页按钮
CarouselPageIndicatorThemeConstants.FramePart "PART_Frame" 指示点主框架