UIView Animation(二)-Transform(Swift)

本文及其之后的讲解是依据Raywenderich 的 Animation Tutorial这一本书和苹果官方文档总结而来,特此声明!

API解读

  • CGAffineTransform
    View的transform是CGAffineTransform类型的属性,官方文档:

A structure for holding an affine transformation matrix
一个用于映射转换矩阵的结构体

//transform 是一种状态,并且只有一种状态,做动画需要结合UIAnimation API使用
public struct CGAffineTransform {
    public var a: CGFloat
    public var b: CGFloat
    public var c: CGFloat
    public var d: CGFloat
    public var tx: CGFloat
    public var ty: CGFloat
    public init()
    public init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat)
}

对应矩阵:


刚开始看着头疼,始终不理解,查了许多资料,看了苹果官方文档,终于明白了!(PS:数学真的很重要,这里牵扯到向量和矩阵,如果不太清楚,请百度)
简单点来说,view是由多个像素块构成的,而transform的作用是通过修改属性值来更改像素点的(x,y),最终达到缩放,旋转和平移的目的!注意:CGAffineTransform只能在二维坐标中操作,如果做3D操作,需要通过核心动画完成(暂时不说核心动画),像素点(x,y)本质是一个二维坐标中的向量,如下图:


Apple提供了一个公式来计算像素点的(x,y),计算时[x,y,1]代表原来的像素块,假设(x’,y’)为更改之后新的像素块,计算公式如下:

两个矩阵相乘:

示意图:

CGAffineTransform默认值为CGAffineTransformIdentity,是一个常量(1,0,0,1,0,0),对应矩阵如下:


  • CGAffineTransformIdentity
    每次操作完成时用来重置,清空所有的设置的transform

  • CGAffineTransformMakeScale(sx: CGFloat, sy: CGFloat) -> CGAffineTransform
    设置缩放比例,sx和sy分别对应x轴方向和y轴方向的缩放比例,由于是缩放比例,不可能缩放成负数,故系统取值时是根据传入值的绝对值来操作,矩阵如下:
    ![](http://upload-images.jianshu.io/upload_images/2361958-3d3381361c1a1b54.png?
    imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    即:CGAffineTransformMake(sx, 0, 0, sy, 0, 0)
    依据上述公式计算结果如下:

  • CGAffineTransformMakeScale(sx: CGFloat, sy: CGFloat) -> CGAffineTransform
    设置旋转角度,传入参数为正时顺时针旋转,传入参数为负时逆时针旋转,矩阵如下:

    即:CGAffineTransformMake(cos a, sin a, -sin a, cos a, 0, 0)
    依据上述公式计算结果如下:

  • CGAffineTransformMakeTranslation(tx: CGFloa, ty: CGFloat) -> CGAffineTransform
    设置平移距离,传入参数为正时,正方向移动,为负时,反方向移动(x:右为正,左为负;y:下为正,上为负),矩阵如下:

    即:CGAffineTransformMake(1, 0, 0, 1, tx, ty)
    依据上述公式计算结果如下:

  • 注意:以上API调用只能变化一次,因为这种方式的变化始终是以最原始的状态值进行变化的,所以只能变化一次!若想多次变换,请调用如下API,使用方法未变,多一个CGAffineTransform参数,每次变化都是以上一次的状态(CGAffineTransform t)进行的变化,所以可以多次变化!
//多次操作时调用
CGAffineTransformScale(t: CGAffineTransform, sx: CGFloat, sy: CGFloat) -> CGAffineTransform
CGAffineTransformRotate(t: CGAffineTransform, angle: CGFloat) -> CGAffineTransform
CGAffineTransformTranslate(t: CGAffineTransform, tx: CGFloat, ty: CGFloat) -> CGAffineTransform

  • 其他API
//将两个操作结合,返回一个CGAffineTransform对象 
 CGAffineTransformConcat(t1: CGAffineTransform, t2: CGAffineTransform) -> CGAffineTransform
//对传入CGAffine对象反向操作
CGAffineTransformInvert(t: CGAffineTransform) -> CGAffineTransform
//判断两个操作是否相同
CGAffineTransformEqualToTransform(t1: CGAffineTransform, _ t2: CGAffineTransform) -> Bool

这些API结合使用,已经可以实现很炫的动效,建议动手试试

Demo

这个Demo,基本用到了前两章所讲到的API,仅供参考

推荐阅读更多精彩内容