今天我们来看看如何实现一个立方体翻转的效果,如图
看上去很麻烦,实际上实现起来还是蛮轻松的。
这里我们使用到的有两个类。
android.graphic.Camera
- 这是在图像学概念里的摄像机,这是一个
透视摄像机
。
android.graphic.Matrix
头疼的钻研路开始
我们先从摄像头上的角度分析:
正常情况下,我们是这么看画面的(那个电池一样的东西就当是摄像头吧)
我们要产生立方体的效果,那逻辑上应该是这么看:
Camera提供了几个接口,我们这使用到的接口有两个:
- Rotate 旋转
- Translate 平移
画布
的!
这里我们首先要有2个View。xml结构入下:
SplashLayout就是我的自定义布局,用来绘制立方体效果的布局。
backgroundView
,第二个View作为foregroundView
,使得效果是从backgroundView
翻转到foregroundView
。
具体代码入下:
ViewGroup
的dispatchDraw
方法里即可,因为ViewGroup
只能在dispatchDraw
方法中绘制子视图。
其中,canvas
代表画布,interpolation
代表动画从0.0 到 1.0 的过程,方便插入器的使用。
这里来解释下我们的过程。
View状态变换
background
是这样的:
- 绕Y轴正方向转90度
- 画布x轴移动到width的位置。
画布2
的状态。
终点状态是这样:
- 绕Y轴正方向0度。
- 画布x轴移动到0的位置。
可以参考上图中的画布的状态。
旋转问题
sFinalDegree
为90。
interpolation
从0到1的过程,
background
的rotate就变成了从90
到0
的过程。
平移问题
平移摄像机
或者直接平移画布
。
这里我们说下区别,如果移动摄像机,会导致图像的投影发生变化,举个例子:
比如我们已经在投影上绕Y轴旋转90度,如果移动X轴的话,看如下图的区别:
1、未平移摄像机
2、平移摄像机
从图上我们知道,这个旋转过的画布的前端和后端我们都是可以看见的,这当然不符合我们要求,那么我们直接平移画布是什么意思呢?1
一样,但是我们的画布却平移了,这就达到了我们最终的要求。
我们看代码虽然我们平移的是画布,但是我们平移的过程中确是使用移动摄像机的方式来绘制投影,这又是为什么呢?
我们从三角函数的投影来解释这个问题。
首先看见我平移摄像头的方式是线性的,也就是y=kt
这种方式,斜率一定,也就是随着时间变化,我平移的距离是线性增加的。那么考虑旋转的时候的投影情况:
被旋转的角就是角a
,我们的画布长为width
,那么画布的投影长度为
width * cos(a)
它是一个三角函数。变化趋势先快后慢,因此我们在旋转过程中会看见右边露出背景,造成视觉上的不友好,怎么解决这个问题呢?
这时候就借助我们的摄像机平移的投影方式。
cos(a) * width
要长很多,因此它就可以让我们在旋转过程中不产生黑边,给人视觉上的饱满感,会让我们的视觉效果好很多。foregroundView
就是一个backgroundView
的逆向过程,因此使用类似的代码,然后假设interpolation
是从1-0的过程即可,同时它的坐标系整体要往左移动一个屏幕。
总结
Camera
来进行辅助我们进行矩阵的计算。
源码