經(jīng)過幾次實(shí)驗(yàn),發(fā)現(xiàn)如果分享的文章能構(gòu)成系列氏豌,效果會(huì)非常好逢渔。同時(shí)自己也能收獲很大递雀,能夠整塊整塊的復(fù)習(xí),也能夠幫助自己更深入的塊狀學(xué)習(xí)知識(shí)悲雳。對自己梳理線條挎峦,整理知識(shí)體系作用非常大。
所以這次還是打算用這種方式合瓢,一起來分享一下iOS中關(guān)于動(dòng)畫的部分坦胶。iOS 的動(dòng)畫渲染簡直是帥的不要不要的,哈哈晴楔。其實(shí)當(dāng)初就是因?yàn)閕OS的動(dòng)畫顿苇,還有iOS的對手勢的處理深深的打動(dòng)了我,才讓我這樣一個(gè)高齡中年老男人開始了iOS這條路税弃。啦啦啦啦~
動(dòng)畫這個(gè)系列大概會(huì)分享五篇文章纪岁,但是也有可能因?yàn)樽约和祽谢蛘咂渌壒矢淖円幌隆oho~
-----------------------華麗分割線钙皮,iOS動(dòng)畫系列全集鏈接-------------------------------------------------
第一篇:iOS動(dòng)畫系列之一:通過實(shí)戰(zhàn)學(xué)習(xí)CALayer和透視的原理蜂科。做一個(gè)帶時(shí)分秒指針的時(shí)鐘動(dòng)畫(上)
第二篇:iOS動(dòng)畫系列之二:通過實(shí)戰(zhàn)學(xué)習(xí)CALayer和透視的原理顽决。做一個(gè)帶時(shí)分秒指針的時(shí)鐘動(dòng)畫短条。包含了OC和Swift兩種源代碼(下)
第三篇:iOS動(dòng)畫系列之三:Core Animation导匣。介紹了Core Animation的常用屬性和方法。
第四篇:CABasic Animation茸时。iOS動(dòng)畫系列之四:基礎(chǔ)動(dòng)畫之平移篇
第五篇:CABasic Animation贡定。iOS動(dòng)畫系列之五:基礎(chǔ)動(dòng)畫之縮放篇&旋轉(zhuǎn)篇
第六篇:iOS動(dòng)畫系列之六:利用CABasic Animation完成帶動(dòng)畫特效的登錄界面
第七篇:iOS動(dòng)畫系列之七:實(shí)現(xiàn)類似Twitter的啟動(dòng)動(dòng)畫
第八篇:iOS動(dòng)畫系列之八:使用CAShapeLayer繪畫動(dòng)態(tài)流量圖
第九篇:iOS動(dòng)畫系列之九:實(shí)現(xiàn)點(diǎn)贊的動(dòng)畫及播放起伏指示器
第十篇:實(shí)戰(zhàn)系列:繪制過山車場景
開始咱們的第一篇內(nèi)容。
1. 最終實(shí)現(xiàn)的效果以及思維導(dǎo)圖
實(shí)現(xiàn)的效果可都。不小心暴露了寫文章的時(shí)間缓待。-_-+++
實(shí)現(xiàn)的步驟思維導(dǎo)圖:
2. CALayer
其實(shí)今天分享的主角是CALayer。因?yàn)樗械膭?dòng)畫都是在CALayer上完成的渠牲。
- 在iOS中旋炒,看得見摸得著的東西基本上都是UIView,比如一個(gè)按鈕签杈、一個(gè)文本標(biāo)簽瘫镇、一個(gè)文本輸入框、一個(gè)圖標(biāo)等等答姥,這些都是UIView
- 其實(shí)UIView之所以能顯示在屏幕上铣除,完全是因?yàn)樗鼉?nèi)部的一個(gè)圖層
- 在創(chuàng)建UIView對象時(shí),UIView內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)圖層(即CALayer對象)鹦付,通過UIView的layer屬性可以訪問這個(gè)層
@property(nonatomic,readonly,retain) CALayer *layer;
- 當(dāng)UIView需要顯示到屏幕上時(shí)尚粘,會(huì)調(diào)用drawRect:方法進(jìn)行繪圖,并且會(huì)將所有內(nèi)容繪制在自己的圖層上敲长,繪圖完畢后郎嫁,系統(tǒng)會(huì)將圖層拷貝到屏幕上,于是就完成了UIView的顯示
- 換句話說祈噪,UIView本身不具備顯示的功能行剂,是它內(nèi)部的層才有顯示功能
2.1 CALayer的基本屬性
屬性類型|屬性名稱|用途
-------|---------
@property CGFloat |borderWidth;|邊寬
@property CGColorRef |borderColor;|邊的顏色
@property CGColorRef |backgroundColor;| 背景顏色
@property float |opacity;|透明度
@property CGColorRef |shadowColor;| 陰影顏色
@property float |shadowOpacity;|陰影透明度,設(shè)置范圍0~1。
@property CGSize |shadowOffset;|陰影的偏移
@property CGFloat |shadowRadius;|陰影的模糊度
@property(strong) id |contents;|內(nèi)容钳降『裨祝可以設(shè)置為圖片,但是需要橋接遂填。
@property CGFloat| cornerRadius;|圓角
@property CGRect |bounds;| Layer的大小
@property CGPoint |position;| 默認(rèn)情況下相當(dāng)于UIView的center
@property CGPoint |anchorPoint;| position的錨點(diǎn)
@property CATransform3D |transform;| 用來做形變的铲觉,是一個(gè)矩陣∠偶幔可以理解為結(jié)構(gòu)體撵幽。
@property BOOL |masksToBounds;|超過部分進(jìn)行裁剪
- 設(shè)置陰影的時(shí)候,陰影顏色+陰影偏移(或者陰影路徑)+陰影透明度缺一不可礁击。
- 陰影模糊度如果不設(shè)置盐杂,默認(rèn)值就是3.0000逗载。
- 陰影的路徑:
- 設(shè)置了陰影的路徑,就不再需要設(shè)置陰影的偏移量了链烈。
- 設(shè)置了陰影的路徑之后厉斟,也不能再設(shè)置
masksToBounds
。因?yàn)槌^部分會(huì)被裁減强衡。
以實(shí)現(xiàn)下圖為例:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:imageView];
// 設(shè)置背景顏色擦秽。注意UIColor 和 CGColor之間的互換
imageView.layer.backgroundColor = [UIColor grayColor].CGColor;
// 生成一個(gè)path
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(-10, -10, imageView.bounds.size.width + 20, imageView.bounds.size.height + 20)];
// 設(shè)置陰影path
imageView.layer.shadowPath = path.CGPath;
// 設(shè)置陰影顏色
imageView.layer.shadowColor = [UIColor lightGrayColor].CGColor;
// 設(shè)置陰影透明度
imageView.layer.shadowOpacity = 0.5;
2.2 手動(dòng)創(chuàng)建一個(gè)CALayer
- 創(chuàng)建CALayer
- 在設(shè)置frame的時(shí)候,內(nèi)部同時(shí)設(shè)置了position,bounds.size 都會(huì)發(fā)生改變漩勤。
- 設(shè)置position感挥,就和設(shè)置UIView的center一樣的。
- 記得要添加到父CALayer上越败。
CALayer *layer = [[CALayer alloc] init];
// ------------------- 設(shè)置位置大小 ---------------------
// 方式一: 直接設(shè)置 frame
// layer.frame = CGRectMake(50, 50, 200, 200);
// 方式二:
// 先設(shè)置大小
layer.bounds = CGRectMake(0, 0, 100, 100);
// 再設(shè)置位置(默認(rèn)情況下 position 指的是 center触幼。)
layer.position = CGPointMake(150, 150);
// ------------------- 設(shè)置位置大小 ---------------------
layer.backgroundColor = [UIColor redColor].CGColor;
layer.opacity = 0.7;
[self.view.layer addSublayer:layer];
}
2.3 transform
從這里開始,咱們的坐標(biāo)軸就變成了xyz三個(gè)軸向了究飞,因?yàn)閳D案也會(huì)變成立體的了置谦。
- 從 layer 的中心點(diǎn)到 給定的坐標(biāo)點(diǎn)之間連一條線, 然后以這個(gè)線為中心軸, 開始旋轉(zhuǎn)
self.myLayer.transform = CATransform3DMakeRotation(M_PI_4, 10, 20, 30);
這段代碼的意思就是說從{0,0,0}這個(gè)點(diǎn),到{10,20,30}這個(gè)點(diǎn)噪猾,劃一根線霉祸。圖形繞著這根線,旋轉(zhuǎn)M_PI_4度數(shù)袱蜡。
2.3.1 修改透視
在真實(shí)世界中丝蹭,當(dāng)物體遠(yuǎn)離我們的時(shí)候,由于視角的原因看起來會(huì)變小坪蚁,理論上說遠(yuǎn)離我們的視圖的邊要比靠近視角的邊跟短奔穿,但實(shí)際上并沒有發(fā)生,而我們當(dāng)前的視角是等距離的敏晤,也就是在3D變換中任然保持平行贱田,和之前提到的仿射變換類似。
“為了做一些修正嘴脾,我們需要引入投影變換(又稱作z變換)來對除了旋轉(zhuǎn)之外的變換矩陣做一些修改男摧,Core Animation并沒有給我們提供設(shè)置透視變換的函數(shù),因此我們需要手動(dòng)修改矩陣值译打,幸運(yùn)的是耗拓,很簡單:
CATransform3D
的透視效果通過一個(gè)矩陣中一個(gè)很簡單的元素來控制:m34。m34用于按比例縮放X和Y的值來計(jì)算到底要離視角多遠(yuǎn)奏司∏茄”
*Excerpt From: 鐘聲. “ios核心動(dòng)畫高級(jí)技巧.” iBooks. *
- 通過修改transform的m34來達(dá)到效果
- transform可以看成是一個(gè)結(jié)構(gòu)體,所以修改的時(shí)候需要通過一個(gè)中間量才能修改韵洋。
- m34的默認(rèn)值是0竿刁,可以通過設(shè)置m34為-1.0 /
d
來應(yīng)用透視效果 -
d
代表了想象中視角相機(jī)和屏幕之間的距離黄锤,以像素為單位,那應(yīng)該如何計(jì)算這個(gè)距離呢食拜?實(shí)際上并不需要鸵熟,大概估算一個(gè)就好了〖嗌簦” - “因?yàn)橐暯窍鄼C(jī)實(shí)際上并不存在旅赢,所以可以根據(jù)屏幕上的顯示效果自由決定它的防止的位置齿桃。通常500-1000就已經(jīng)很好了”
Excerpt From: 鐘聲. “ios核心動(dòng)畫高級(jí)技巧.” iBooks.
struct CATransform3D{
CGFloat m11(x縮放), m12(y切變), m13(旋轉(zhuǎn)), m14();
CGFloat m21(x切變), m22(y縮放), m23, m24;
CGFloat m31(旋轉(zhuǎn)), m32, m33, m34(透視效果惑惶,要有旋轉(zhuǎn)角度才能看出效果);
CGFloat m41(x平移), m42(y平移), m43(z平移), m44;
};
struct CGAffineTransform {
CGFloat a, b, c, d;
CGFloat tx, ty;
};
// 定義矩陣
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0 / 800;
// 旋轉(zhuǎn)加透視
transform = CATransform3DRotate(transform, -M_PI_4, 0, 1, 0);
imageView.layer.transform = transform;
2.3.2 縮放
//方式一:
transform = CATransform3DMakeScale(<#CGFloat sx#>, <#CGFloat sy#>, <#CGFloat sz#>)
//方式二:
transform = CATransform3DScale(imageView.layer.transform, <#CGFloat sx#>, <#CGFloat sy#>, <#CGFloat sz#>)
2.4 重要屬性之position和anchorPoint
- 默認(rèn)情況下position相當(dāng)于UIView 的center
- position決定了layer在父上的位置。
- 但是anchorPoint決定了position在自身的位置短纵。
- anchorPoint的數(shù)值只能是0~1带污。所以是按照百分比計(jì)算的。
3. 隱式動(dòng)畫
- 當(dāng)對非Root Layer的部分屬性進(jìn)行修改時(shí)香到,默認(rèn)會(huì)自動(dòng)產(chǎn)生一些動(dòng)畫效果
- 所有的非Root Layer鱼冀,也就是手動(dòng)創(chuàng)建的CALayer對象,都存在著隱式動(dòng)畫
- 所有注釋里面寫著有Animatable悠就,這個(gè)屬性就有隱式動(dòng)畫效果千绪。
3.1 幾個(gè)常見的Animatable Properties:
- bounds:用于設(shè)置CALayer的寬度和高度。修改這個(gè)屬性會(huì)產(chǎn)生縮放動(dòng)畫
- backgroundColor:用于設(shè)置CALayer的背景色梗脾。修改這個(gè)屬性會(huì)產(chǎn)生背景色的漸變動(dòng)畫
- position:用于設(shè)置CALayer的位置荸型。修改這個(gè)屬性會(huì)產(chǎn)生平移動(dòng)畫
3.2 關(guān)閉隱式動(dòng)畫
- 可以通過動(dòng)畫事務(wù)(CATransaction)關(guān)閉默認(rèn)的隱式動(dòng)畫效果
- 關(guān)閉或者修改隱式動(dòng)畫的步驟:
- 開啟動(dòng)畫事物
- 關(guān)閉動(dòng)畫效果或者修改動(dòng)畫事件
- 設(shè)置動(dòng)畫完成后的動(dòng)作(可以不設(shè)置)
- 修改屬性
- 提交
//開啟
[CATransaction begin];
//關(guān)閉動(dòng)畫
[CATransaction setDisableActions:YES];
//修改屬性
self.myview.layer.position = CGPointMake(10, 10);
//提交
[CATransaction commit];
寶貝兒們,我錯(cuò)了炸茧。寫到這里發(fā)現(xiàn)已經(jīng)辣么長辣么長了瑞妇,再寫下去這篇該沒有人看了。
那么梭冠,那么辕狰。。控漠。蔓倍。就臨時(shí)變卦吧,把這篇文章變成上下集吧盐捷。哈哈~就這么愉快的自己打自己的臉了偶翅,文章開始還說要五篇~
所以,證明一個(gè)道理毙驯。計(jì)劃都只是用來計(jì)劃的倒堕,樹立一個(gè)目標(biāo),能不能實(shí)現(xiàn)再說爆价。哈哈~