粉骨碎身全不怕, 要留清白在人間!<小拳石>
基礎知識:
iOS能夠實現動畫的方式:(如上圖)
- UIView基礎實現方式一
- UIView基礎實現方式二
- CoreAnimation實現方式
動畫的效果簡述:
- 傳達狀態
- 提高用戶對直接操作的感知
- 幫助用戶可視化操作的結果
UIVIew 的基礎動畫:
- UIKit直接將動畫繼承到UIView類中, 當內部的一些屬性發生改變時, UIView將為這些改變提供動畫支持.
- 執行動畫的工作由UIView類自動完成, 但希望在執行動畫時通知視圖, 為此需要將改變屬性的代碼放在
[UIView beginAnimations: nil context: nil]
和[UIView commitAnimations]
之間.
代碼部分詳細介紹相關屬性
CALayer基本介紹:
- CALayer負責繪制, 提供UIView需要展示的內容, 不能交互
- UIView負責交互,顯示CALayer繪制的內容
- CALayer(層)是屏幕上的一個矩形區域, 在每一個UIView中都包含一個根
- CALayer, 在UIView上的所以視覺效果都是在這個Layer上進行的.
1: 在 iOS 中, 我們能看見的, 例如按鈕, 文本, 標簽, 輸入框, 等等 都是 UIView
2: 其實 UIView 之所以能顯示在屏幕上, 完全是因為它內部的一個圖層, 在創建 UIView 對象的時候, UIView 內部會自動創建一個圖層就是(CALayer 對象), 通過 UIView 的 layer 屬性就可以訪問這個層
3: 當 UIView 需要顯示到屏幕上時, 會調用 drawRect: 方法進行繪圖, 并且將所有的繪制內容在自己的圖層上繪制, 給圖層繪制完畢后, 系統將會拷貝圖層到屏幕上, 完成 UIView 的顯示
4: UIVIew 本身是不具備顯示功能的, 真正擁有顯示功能的是里面的 layer 層
5: 通過 UIView 的圖層, 可以調整 UIView 的一些界面屬性, 例如陰影 圓角 邊框 顏色
CALayer外形特征主要包括:
- 層的大小尺寸
- 背景色
- 內容(可以填充圖片或者使用Core Graphics繪制的內容)
- 積習是否使用圓角
- 矩形是否有陰影
CALayer常用屬性:
與UIView動畫相比, CoreAnimation能夠實現更多復雜, 好看, 高效的動畫效果:
- 陰影, 圓角, 帶顏色的邊框
3D變換
透明遮罩
多級非線性動畫
-
CALayer的坐標系統比UIView多了一個anchorPoint屬性
anchorPoint錨點相對自身bounds來說,默認值為(0.5,0.5),即是anchorPoint的默認值在layer的中心點,它的值在0~1之間
簡單圖示錨點
CoreAnimation動畫
CoreAnimation動畫位于iOS框架的Media層
CoreAnimation動畫實現需要添加QuartzCore.Framework
CoreAnimation基本上是Layer Animation
CABasicAnimation基本單一類型的動畫
CAKeyframeAnimation 幀動畫, 主要操作屬性與keyPath 和 values值組合
CAAnimationGroup組合動畫, 操作屬性: animations將CAAnimation類型的動畫加入數組, FIFO隊列的方式執行
1: 核心動畫的基本概念
① core Animation, 核心動畫, 是一組非常強大的動畫處理 API, 可以用少量的代碼, 實現強大的功能
② core Animation, 可以用在 Mac OS 和 iOS 兩個平臺
③ core Animation, 動畫的執行過程, 都是在后臺操作的, 所以不會阻塞主線程
④ core Animation, 是直接操作 CALayer 層的, 并不是 UIView
2: CAAnimation
① 所有動畫的父類, 負責控制動畫的持續時間和速度, 他是一個抽象的類, 不能直接使用, 應該使用他的子類
② 屬性說明:
- duration: 動畫的持續時間
- repeatCount: 動畫的重復次數
- repeatDuration: 重復時間
- removeOnCompletion (BOOL): 默認為 YES, 表示動畫執行完畢后就從圖層上移除, 圖形會恢復到執行之前的狀態. 如果想要保持執行之后的狀態, 那就設置 NO, 但是, 還需要設置 fillMode 值為 kCAFillModeForwards
- fillModel: 決定當前對象在非活動的時間段的行為, 比如動畫開始前或者動畫結束之后 (想要 fillMode 有效, 最好將removeOnCompletion = 0);
- kCAFillModeRemove:
默認值也就是當前動畫開始前和動畫結束后, 動畫對 layer 都沒有影響, 動畫結束后, layer 會恢復之前的狀態
- kCAFillModeForwards:
當前結束動畫后, layer 會一直保持最后的狀態 - kCAFillModeBackwards:
在動畫開始之前, 只需要將動畫加入一個 layer, layer 便立即進入動畫的初始狀態并等待動畫的開始. - kCAFillModeBoth: 就是上面兩個 kCAFillModeForwards 和kCAFillModeBackwards 的合成
- beginTime: 可以用來設置動畫的延遲時間, 若想設置延遲 2秒, 那么就設置 CACurrentMediaTime() + 2 CACurrentMediaTime()圖層當前的時間
- timeFuncation: 速度控制函數 控制動畫運行的節奏
---> CAMediaTimingFunctionLinear (線性): 勻速, 給你一個相對靜態的感覺
---> CAMediaTimingFunctionEaseIn (淡入): 動畫緩慢進入, 然后加速離開
---> CAMediaTimingFunctionEaseOut (淡出): 動畫全速進入, 然后減速到達目的地
---> CAMediaTimingFunctionEaseInEaseOut (淡入淡出)
③ CAAnimation 的子類
- CABasicAnimation
- CALeyFrameAnimation
- CAAnimationGroup
- CASpringAnimation
④ 屬性說明
- keypath: 通過制定 CALayer 的一個屬性名稱為 keypath(NSString 類型) , 并且對 CALayer 這個屬性值進行修改, 達到相應的動畫效果, 比如, 制定@"postion"為 keypath , 就相當于修改了 CALayer 的 poison 屬性的值,達到平移的動畫效果.
- 下面的代碼部分會對這個 關建路徑支持結構字段 進行相應的總結
- 關鍵路徑支持的部分字段補充說明
margin = 布局
zPosition = 翻轉
backgroundColor = 背景顏色
cornerRadius = 圓角
borderWidth = 邊框寬
bounds = 大小
contents = 內容
contentsRect = 內容大小
cornerRadius = 圓角
frame = 大小位置
hidden = 顯示隱藏
mask 遮罩
masksToBounds
opacity 不透明的
position 位置
shadowColor 陰影顏色
shadowOffset 陰影偏移量
shadowOpacity 陰影不透明的
shadowRadius 陰影半徑
transform.scale = 比例轉換
transform.scale.x =以 x軸 比例轉換
transform.scale.y = 以 y軸 比例轉換
transform.rotation.z = 平面圓形旋轉
3: 關鍵幀動畫 與 CABasicAnimation 的區別
① CABasicAnimation只能從一個數值(fromvalue) 變換到另外一個數值 (tovaule)
② 關鍵幀動畫, 會使用一個 NSArray 保存這些數值
4: 動畫組
① 屬性說明:
- animations: 用來保存一組動畫對象NSArray
- 默認情況下, 一組動畫對象是同時運動的, 也可以通過設置動畫的 beginTime 屬性來更改動畫的開始時間
5: 轉場動畫 -------- CATransition: --------------
CATransition: 用于做轉場動畫效果, 能夠為 layer 層提供移出屏幕和移入屏幕的動畫效果
① 動畫屬性:
- type: 動畫的過渡效果
類型字符串 效果說明
fade 交叉淡化過渡
push 新視圖把舊視圖推出去
moveIn 新視圖移到舊視圖上面
reveal 將舊視圖移開,顯示下面的新視圖
cube 立方體翻轉效果
oglFlip 上下左右翻轉效果
suckEffect 收縮效果,像一塊布被抽走
rippleEffect 水滴效果
pageCurl 向上翻頁效果
pageUnCurl 向下翻頁效果
cameraIrisHollowOpen 相機鏡頭打開效果
cameraIrisHollowClose 相機鏡頭關閉效果
- subtype: 動畫的過渡方向
- startProgress: 動畫的起點(在整個動畫的百分比)
- endProgress: 動畫的終點
UIView 的基礎動畫 代碼總結
實例1: 自定義一個屬性 MyLabel (UILabel)類型的 展示的是 UIView 的動畫效果, 在一個觸發方法里面實現動畫,我這里寫在 TouchBegin 里面.
//1. 創建一個動畫
[UIView beginAnimations:nil context:nil];
//2. 動畫延遲設置
[UIView setAnimationDelay:1];
//3. 給動畫添加代理(不遵循代理協議, 也能實現代理方法)
[UIView setAnimationDelegate:self];
//4. 給動畫添加方法(動畫結束后執行)
[UIView setAnimationDidStopSelector:@selector(stopAc)];
//5. 動畫持續時間(完成動畫所需時間)
[UIView setAnimationDuration:2];
//6. 設置動畫是否會做一次反向的執行 (等會屬性里面再說)
[UIView setAnimationRepeatAutoreverses:YES];
//7. 設置動畫移動的新位置
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
//8. 開始提交動畫 (解釋可以看下面)
[UIView commitAnimations];
總結一下這里涉及的方法: 均是 UIView 的類方法
- 第 1個方法: 動畫馬上開始:begin
+(void)beginAnimations:(NSString*)animationID context:(void *)context{}
# 參數1: animationID 作為動畫的標示使用, 可以方便移除動畫操作
# 參數2: context 動畫的設置 自定義的一些動畫數據,這些數據將發送給動畫的代理方法 默認 nil
- 最后 1 個方法: commit
# 這個方法 就是提交動畫 也是標記動畫的內容已經編輯好了 可以使用效果了
+ (void)commitAnimations
在這兩個方法之間就我們進行,動畫相關的一些設置,下面是一些設置的方法
# 設置代理 及其 方法不需要設置遵循代理方法 默認 nil 沒有代理
+ (void)setAnimationDelegate:(nullable id)delegate;
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
# 設置動畫持續時間 默認 = 0.2
+ (void)setAnimationDuration:(NSTimeInterval)duration;
# 設置動畫的延遲時間 默認是不延遲 就是0.00
+ (void)setAnimationDelay:(NSTimeInterval)delay;
# 設置動畫的開始時間 default = now ([NSDate date])
+ (void)setAnimationStartDate:(NSDate *)startDate;
# 設置動畫的曲線方式(動畫的總體變化的時間曲線:開始快最后慢,開始慢最后快,最后慢,均勻線性) 默認default = UIViewAnimationCurveEaseInOut
/*typedef NS_ENUM(NSInteger, UIViewAnimationCurve){
UIViewAnimationCurveEaseInOut,
UIViewAnimationCurveEaseIn,
UIViewAnimationCurveEaseOut,
UIViewAnimationCurveLinear
};
*/
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
# 動畫的重復次數 default = 0.0.
+ (void)setAnimationRepeatCount:(float)repeatCount;
# 設置動畫是否做一次反向的執行。
/*如果設置為YES:動畫將執行:動畫初始狀態->動畫->動畫完成狀態->動畫->動畫初始狀態 。
如果設置為NO:默認值*/
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
# 設置動畫的開始狀態
/*
YES : 第一個動畫正在 執行時候, 另一個動畫恰好開始, 這樣第一個動畫的當前狀態, 就是另一個動畫的開始狀態
NO: 第一個達到完成狀態, 下一個動畫才開始執行動畫的效果
*/
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
# 設置視圖view的過渡效果, transition指定過渡類型, cache設置YES代表使用視圖緩存,性能較好
/*
UIView官方提供五種動畫效果供大家使用,分別為:
UIViewAnimationTransitionNone 不使用動畫
UIViewAnimationTransitionFlipFromLeft 從左向右旋轉翻頁
UIViewAnimationTransitionFlipFromRight 從右向左旋轉翻頁
UIViewAnimationTransitionCurlUp 卷曲翻頁,從下往上
UIViewAnimationTransitionCurlDown 卷曲翻頁,從上往下
*/
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
# 設置view是否有動畫效果
/*
YES: 默認有動畫的能力
NO: 關閉動畫效果
效果關閉并不會對 UI 的改變有什么影響只是不會 "動畫" 了而已, 其他的大小什么屬性依然有效的
*/
+ (void)setAnimationsEnabled:(BOOL)enabled;
# 判斷當前的動畫效果是否關閉了
+ (BOOL)areAnimationsEnabled;
通過 UIView 的幾個 Block 方法進行動畫設置
- // 實現動畫 的 Block1
參數1 : Duration 動畫持續時間 Block 里面就寫你要實現的效果(位置的改變等)
[UIView animateWithDuration:2 animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
}];
- // 實現動畫 的 Block2
```code
# 參數比上面多一個 動畫結束后的操作
[UIView animateWithDuration:2 animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 200, 200);
} completion:^(BOOL finished) {
NSLog(@"動畫結束的操作可以寫這里");
}];```
- // 實現動畫 的 Block3
```code
/*
參數1: Duration: 動畫持續時間
參數2: delay: 延遲時間
參數3: options: 枚舉值 動畫的效果類型*/
[UIView animateWithDuration:2 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
} completion:^(BOOL finished) {
NSLog(@"結束了%d", finished);
}];```
- //實現動畫的Block4 彈簧效果
```code
/*
Spring: 模擬彈簧彈跳的效果
參數: Damping:阻尼 0-1 阻尼越小動畫越明顯
參數: initialSpringVelocity : 動畫初始變化速度
參數: options 轉變的風格 枚舉值
*/
[UIView animateWithDuration:10 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:15 options:(UIViewAnimationOptionCurveEaseInOut) animations:^{
self.MyLabel.center = CGPointMake(self.view.center.x, 100);
} completion:^(BOOL finished) {
NSLog(@"彈簧效果結束");
}];```
- //實現動畫的Block5 關鍵幀動畫 也就是里面有好幾個動畫進行轉變
```code
/*
Duration:持續時間
delay: 延遲時間
options: 枚舉值 動畫的風格
*/
[UIView animateKeyframesWithDuration:3 delay:0 options:(UIViewKeyframeAnimationOptionRepeat) animations:^{
/*
參數1: RelativeStartTime: 相對的開始時間
參數2: relativeDuration:相對持續時間
*/
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
self.MyLabel.center = self.view.center;
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.3 animations:^{
self.MyLabel.frame = CGRectMake(100, 100, 100, 100);
}];
[UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:0.3 animations:^{
self.MyLabel.frame = CGRectMake(100, 400, 100, 100);
}];
} completion:^(BOOL finished) {
NSLog(@"結束了");
}];
- CAAnimation 的子類
------------ CABasicAnimation -----------------
# 1: 創建 以字段為 旋轉變換
CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
# 動畫效果的初始值
basic.fromValue = @0;
# 動畫效果變化的結束值 (絕對值) 這里就是旋轉的角度從多少轉到多少度
basic.toValue = @(2*M_PI);
# 動畫執行時間
basic.duration = 5;
# Layer 動畫需要天加到 layer 上 forkey 我們可以寫上我們標記的動畫屬性
[self.MyLabel.layer addAnimation:basic forKey:@"transform.rotation"];
--------- CAKeyFramAnimation 關鍵幀動畫--------
// 創建 以關鍵字段 位置變化
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 建幾個動畫的位置
CGPoint p1 = CGPointMake(0, 0);
CGPoint p2 = CGPointMake(0, 400);
CGPoint p3 = CGPointMake(400, 100);
CGPoint p4 = CGPointMake(100, 200);
CGPoint p5 = CGPointMake(200, 300);
NSValue *v1 = [NSValue valueWithCGPoint:p1];
NSValue *v2 = [NSValue valueWithCGPoint:p2];
NSValue *v3 = [NSValue valueWithCGPoint:p3];
NSValue *v4 = [NSValue valueWithCGPoint:p4];
NSValue *v5 = [NSValue valueWithCGPoint:p5];
//屬性 values : 數組對象 里面的元素稱為"keyFrame"(關鍵幀), 動畫對象會在指定的時間里 (duration). 依次顯示values 數組中的每一個關鍵幀
keyframe.values = @[v1,v2,v3,v4,v5];
keyframe.duration = 10;
// 每一幀的時間, 每一幀的時間為比例的累加計算 取值范圍 0-1,沒有設置的話 每一幀的時間是平分的
keyframe.keyTimes = @[@0.1,@0.1,@0.1,@0.1];
[self.MyLabel.layer addAnimation:keyframe forKey:@"系統保留關鍵字"];
--------- CAAnimationGroup 動畫組--------
// 創建
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 10;
// 把上面兩個動畫加到這個動畫組里面
group.animations = @[basic,keyframe];
[self.MyLabel.layer addAnimation:group forKey:@"同上"];
--------------- CASpringAnimation 模擬彈簧動畫效果--------
// 創建一個彈簧動畫 結構關鍵字段 意思是豎直方向上 模擬彈簧
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"position.y"];
// 設置動畫效果的初始值
spring.fromValue = @50;
// 設置動畫的結束值
spring.toValue = @10;
// 阻尼系數
spring.damping = 0.1;
// 剛度系數: (勁度系數 / 彈性系數): 系數越大,形變的產生的力越大, 運動越快
spring.stiffness = 10;
// 質量: 影響圖層運動時候的慣性, 質量越大彈簧拉伸和壓縮的幅度越大 (動畫的幅度,波動變大)
spring.mass = 1;
// 初識速率: 動畫視圖的初識速度大小
// 速率為正時候, 速度方向與運動方向一致, 否則相仿.
spring.initialVelocity = 1;
// settlingDuration 結算時間,預估彈簧動畫到停住的時間的估算, 根據當前動畫的各個參數估算, 通常彈簧動畫的估算時間使用結算時間比較準確
spring.duration = spring.settlingDuration;
[self.MyLabel.layer addAnimation:spring forKey:@"彈簧"];
---------- CATransition -------
// 創建
CATransition *trans = [CATransition animation];
// 效果
trans.type = @"pageCurl";
// 開始位置 (0-1)
trans.startProgress = 0;
// 結束位置 (0-1)
trans.endProgress = 1;
// 效果方向
trans.subtype = kCATransitionFromLeft;
// 重復次數
trans.repeatCount = 10;
// 持續時間
trans.duration = 3;
[self.MyView.layer addAnimation:trans forKey:@"11"];