跳转到内容
新建笔记

CarouselEffect实现桌面切换效果的程序具体流程

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) * radius
Z坐标 = sin(angle) * radius
缩放比例 = 1.0 - (1.0 - depthScale) * (Z / radius)
对于目标页面:
旋转角度 = progress * π + π (从π到2π)
X坐标 = cos(angle) * radius
Z坐标 = sin(angle) * radius
缩放比例 = 1.0 - (1.0 - depthScale) * (Z / radius)
+------------------+ +--------------------+ +--------------------+
| 用户操作触发切换 | --> | transitionToPage() | --> | setCurrentIndex() |
+------------------+ +--------------------+ +--------------------+
|
v
+---------------------+ +-------------------+ +----------------+
| 更新显示最终状态 | <-- | 每帧更新页面位置 | <-- | 启动属性动画 |
+---------------------+ +-------------------+ +----------------+
^ |
| v
+------------------------+
| paintCurrentFrame() |
| - 计算各页面位置 |
| - 应用3D变换 |
| - 绘制到临时控件 |
+------------------------+
+------------------------------------------+
| QStackedWidget |
| +------------------------------------+ |
| | TransitionWidget | | <- 动画期间覆盖在
| | (显示动画中间状态的临时控件) | | StackedWidget上
| | | |
| | +----------+ +----------+ | |
| | | | | | | |
| | | 当前页面 | --> | 目标页面 | | |
| | | (变换中) | | (变换中) | | |
| | +----------+ +----------+ | |
| +------------------------------------+ |
+------------------------------------------+

通过这种3D变换和渐进式的动画,CarouselEffect 创建了一种视觉上流畅的旋转木马效果,使得桌面页面切换更加自然和引人入胜。


来源:CSDN 原文,首次发布于 2025-05-18。