仿射变换-CGAffineTransform

CGAffineTransform是iOS封装的一套用于实现仿射变换效果的API,用于绘制2D图形,可以进行位移、旋转、缩放、叠加等效果,常用方法如下:

/** 位移仿射 */
init(translationX tx: CGFloat, y ty: CGFloat)
translatedBy(x tx: CGFloat, y ty: CGFloat)

/** 缩放仿射 */
init(scaleX sx: CGFloat, y sy: CGFloat)
scaledBy(x sx: CGFloat, y sy: CGFloat) 

/** 旋转仿射 */init(rotationAngle angle: CGFloat)
rotated(by angle: CGFloat) -> CGAffineTransform

/** 叠加仿射 */
concatenating(_ t2: CGAffineTransform)

CGAffineTransform原理

CGAffineTransform --view的2D变换运用得是矩阵乘法,通过最基础的仿射方法init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat),可以发现他有6个参数,可以拼出一下矩阵:

矩阵.png

仿射变换的矩阵计算:

屏幕快照 2018-09-26 下午2.40.13.png

根据矩阵计算规则我们可以得到:

x' = ax + cy + tx
y' = bx + dy + ty

实践运用

平移

屏幕快照 2018-09-26 下午3.29.21.png

代码如下:

/** t' = [ 1 0 0 1 tx ty ] */
UIView.animate(withDuration: 1) {  
  _ = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 100, ty: 100)   
  self.redView?.transform = CGAffineTransform(translationX: 100, y: 100)  
  print(NSStringFromCGRect((self.redView?.frame)!)) 
}

输出结果为:{{200, 200}, {100, 100}}

QQ20180926-145732-HD.gif

注: 当tx为正值时,会向x轴正方向平移,反之,则向x轴负方向平移;当ty为正值时,会向y轴正方向平移,反之,则向y轴负方向平移

缩放

屏幕快照 2018-09-26 下午3.31.24.png

代码如下:

/** t' = [ sx 0 0 sy 0 0 ] */
UIView.animate(withDuration: 1) {  
  self.redView?.transform = CGAffineTransform(scaleX: 2, y: 2)
  print(NSStringFromCGRect((self.redView?.frame)!))
}

注: 当sx为正值时,会在x轴方向上缩放x倍,反之,则在缩放的基础上沿着竖直线翻转;当sy为正值时,会在y轴方向上缩放y倍,反之,则在缩放的基础上沿着水平线翻转

效果图:

QQ20180926-153401-HD.gif

旋转

屏幕快照 2018-09-26 下午3.35.31.png

代码如下:

/** t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] */
UIView.animate(withDuration: 1) {  
self.redView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI_2))  print(NSStringFromCGRect((self.redView?.frame)!))
}

效果图:

QQ20180926-154049-HD.gif

注1: 当angle为正值时,时针旋转坐标系统,反之时针旋转坐标系统

CATransform3D仿射变换

3D仿射在iOS中是通过CATransform3D实现的,它有着与CGAffineTrans类似的一组API,但他们有个重要的区别在于CATransform3D的效果只能加在layer的transform属性上,而CGAffineTransform直接加在View上。

3D仿射矩

类似于2D仿射,3D仿射也有一个基础矩阵,并且比2D的多一个维度,计算规则如下:

屏幕快照 2018-09-26 下午3.47.33.png

根据矩阵计算规则我们可以得到:

x' = m11x + m21y + m31*z + m41(tx)

y' = m12x + m22y + m32*z + m42(ty)

z' = m13x + m23y + m33*z + m43(tx)

CATransform3D有16个存储属性,含义如下:

平移因子: m41(x位置) m42(y位置) m43(z位置) 缩放因子: m11(x位置) m22(y位置)
切变因子: m21(x位置) m12(y位置)
旋转因子: m13(x位置) m31(y位置)
透视因子: m34(有旋转才能看出效果

常用方法:

/** 旋转动画 */
CATransform3DMakeRotation(_ angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -> CATransform3D 
/** 缩放动画 */
CATransform3DMakeScale(_ sx: CGFloat, _ sy: CGFloat, _ sz: CGFloat) -> CATransform3D /** 位移动画 */
CATransform3DMakeTranslation(_ tx: CGFloat, _ ty: CGFloat, _ tz: CGFloat) -> CATransform3D 
/** 检查2个3D仿射效果是否相同 */
CATransform3DEqualToTransform(_ a: CATransform3D, _ b: CATransform3D) -> Bool 
/** 检查是否有做过仿射3D效果 */
CATransform3DIsIdentity(_ t: CATransform3D) -> Bool 
/** 3D仿射转换成2D仿射 */
CATransform3DGetAffineTransform(_ t: CATransform3D) -> CGAffineTransform 
/** 2D仿射转换成3D仿射 */
CATransform3DMakeAffineTransform(_ m: CGAffineTransform) -> CATransform3D 
/** 3D仿射效果反转(反效果,比如原来扩大,就变成缩小) */
CATransform3DInvert(_ t: CATransform3D) -> CATransform3D 
/** 叠加3D仿射效果 */
CATransform3DConcat(_ a: CATransform3D, _ b: CATransform3D) -> CATransform3D 
/*    这个是一个初始化矩阵,带入矩阵算法计算后的结构会得到    x'=x , y'=y , z'=z    它的作用是清除之前对矩阵设置的仿射效果,或者用来初始化一个原始无效果的仿射矩阵    
        [ 1 0 0 0 ]    
        [ 0 1 0 0 ]    
        [ 0 0 1 0 ]    
        [ 0 0 0 1 ]*/
CATransform3DIdentity: CATransform3D

实战:

代码如下:

   static var j = 0
    @objc func touches3DTransform() {
        switch ViewController.j {
        case 0:
            /** 旋转 */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DMakeRotation(CGFloat(M_PI), 0, 0, 1)
            }
        case 1:
            /** 平移 t' =  [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1] */
            /**  */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DMakeTranslation(100, 100, 100)
            }
        case 2:
            /** 缩放 t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 1] */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform =  CATransform3DMakeScale(2, 1, 1)
            }
        case 3:
            /** 旋转缩放 t' = rotation(angle, x, y, z) * t */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DRotate(CATransform3DMakeScale(1, 1, 1), CGFloat(M_PI), 0, 1, 0)
            }
            print(NSStringFromCGRect((blueBtn?.frame)!))
        case 4:
            /** 反转 */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DInvert(CATransform3DMakeScale(2, 2, 1))
            }
            print(NSStringFromCGRect((blueBtn?.frame)!))
        default:
            print("other")
        }
        ViewController.j += 1
    }

效果图:

缩放旋转.gif

参考资料:http://liuyanwei.jumppo.com/2015/11/24/iOS-affine-transfermation-animation.html

--------------------- 本文来自 蜗牛非牛 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_34003239/article/details/82852822?utm_source=copy

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容