1. 旋转木马效果基本原理示意图
跳转到“1. 旋转木马效果基本原理示意图” [Page 3] ^ |[Page 2]<--->[Page 4] | v [Page 1]旋转木马效果模拟页面在一个圆形轨道上旋转,当前页面位于圆环正前方,其他页面分布在圆环上的不同位置。
2. 页面在旋转木马上的分布(俯视图)
跳转到“2. 页面在旋转木马上的分布(俯视图)” 前方(用户视角)
[当前页面] | | v [左侧页面] <--- O ---> [右侧页面] /\ / \ / \ / \ [背面页面] [背面页面]- O: 旋转中心点
- 当前页面: 位于前方,完全可见,大小为100%
- 侧面页面: 位于左右两侧,部分可见,有透视效果(缩小)
- 背面页面: 位于背面,几乎不可见,尺寸最小
3. 页面切换过程的变化(从上往下是时间流)
跳转到“3. 页面切换过程的变化(从上往下是时间流)”时间1 (progress = 0.0):+---------------------------------+| [页面A] | <- 当前页面(前方)| || [页面D] [页面B] | <- 侧面页面| || [页面C] | <- 背面页面+---------------------------------+
时间2 (progress = 0.3):+---------------------------------+| || [页面A] [页面B] | <- 页面A向左旋转| | <- 页面B开始前移| [页面D] [页面C] |+---------------------------------+
时间3 (progress = 0.5):+---------------------------------+| || [页面D] [页面B] | <- 页面B继续前移| || [页面A] [页面C] | <- 页面A继续左旋+---------------------------------+
时间4 (progress = 0.7):+---------------------------------+| || [页面D] [页面B] | <- 页面B接近前方| || [页面C] [页面A] | <- 页面A接近背面+---------------------------------+
时间5 (progress = 1.0):+---------------------------------+| [页面B] | <- 新的当前页面| || [页面D] [页面C] | <- 侧面页面| || [页面A] | <- 原页面现在在背面+---------------------------------+4. 单个页面在切换过程中的变化
跳转到“4. 单个页面在切换过程中的变化”切换过程中的页面A (从当前页面变为背面页面):
正视图 侧视图+---------+ +---------+| | | | progress = 0.0| 页面A | | 页面A | 尺寸: 100%| | | | 位置: 前方中央+---------+ +---------+
+---------+ +---------+ | | / / | 页面A | / 页面A / progress = 0.3 | | / / 尺寸: 90% +---------+ +---------+ 位置: 右前方
+---------+ +---------+ | | / / | 页面A | / 页面A / progress = 0.6 | | / / 尺寸: 80% +---------+ +---------+ 位置: 右侧
+-------+ +-------+ | | / / | 页面A | / 页面A / progress = 0.8 | | / / 尺寸: 70% +-------++-------+ 位置: 右后方
+-----+ +-----+ | | / / |页面A| /页面A/ progress = 1.0 | | / / 尺寸: 60% +-----++-----+ 位置: 背面5. 计算坐标变换的数学关系
跳转到“5. 计算坐标变换的数学关系”假设:- radius = 旋转半径(如页面宽度的60%)- progress = 动画进度(0~1)- depthScale = 深度缩放系数(如0.6,表示最小缩放到60%)
对于当前页面:旋转角度 = progress * π (从0到π)X坐标 = cos(angle) * radiusZ坐标 = sin(angle) * radius缩放比例 = 1.0 - (1.0 - depthScale) * (Z / radius)
对于目标页面:旋转角度 = progress * π + π (从π到2π)X坐标 = cos(angle) * radiusZ坐标 = sin(angle) * radius缩放比例 = 1.0 - (1.0 - depthScale) * (Z / radius)6. 代码执行流程图
跳转到“6. 代码执行流程图”+------------------+ +--------------------+ +--------------------+| 用户操作触发切换 | --> | transitionToPage() | --> | setCurrentIndex() |+------------------+ +--------------------+ +--------------------+ | v+---------------------+ +-------------------+ +----------------+| 更新显示最终状态 | <-- | 每帧更新页面位置 | <-- | 启动属性动画 |+---------------------+ +-------------------+ +----------------+ ^ | | v +------------------------+ | paintCurrentFrame() | | - 计算各页面位置 | | - 应用3D变换 | | - 绘制到临时控件 | +------------------------+7. 实现原理示意图
跳转到“7. 实现原理示意图”+------------------------------------------+| QStackedWidget || +------------------------------------+ || | TransitionWidget | | <- 动画期间覆盖在| | (显示动画中间状态的临时控件) | | StackedWidget上| | | || | +----------+ +----------+ | || | | | | | | || | | 当前页面 | --> | 目标页面 | | || | | (变换中) | | (变换中) | | || | +----------+ +----------+ | || +------------------------------------+ |+------------------------------------------+通过这种3D变换和渐进式的动画,CarouselEffect 创建了一种视觉上流畅的旋转木马效果,使得桌面页面切换更加自然和引人入胜。
来源:CSDN 原文,首次发布于 2025-05-18。