目錄
- 一、前言
- 二、UIView Animation
- 2.1 簡單影片
- 2.2 關鍵幀影片
- 2.3 View 的轉換
- 三、CALayer Animation
- 3.1 基本影片(CABasicAnimation)
- 3.2 關鍵幀影片(CAKeyframeAnimation)
- 3.3 影片組(CAAnimationGroup)
- 3.4 切換影片(CATransition)
- 四、后記
一、前言
影片一直是 iOS 開發中很重要的一部分,設計良好,效果炫酷的影片往往能對用戶體驗的提升起到很大的作用,在這里將自己學習 iOS 影片的體會記錄下來,希望能對別人有所幫助,
iOS 的影片框架,即 CoreAnimation,本身十分龐大和復雜,這里暫時分兩個部分進行介紹,分別是 UIView 影片 和 CALayer 影片,
二、UIView Animation
2.1 簡單影片
對于 UIView 上簡單的影片,iOS 提供了很方便的函式:
animateWithDuration:animations:
- 第一個引數是影片的持續時間,
- 第二個引數是一個 block,在
animations block中對 UIView 的屬性進行調整,設定 UIView 影片結束后最終的效果,iOS 就會自動補充中間幀,形成影片,
可以更改的屬性有:
frameboundscentertransformalphabackgroundColorcontentStretch
這些屬性大都是 View 的基本屬性,下面是一個例子,這個例子中的影片會同時改變 View 的 frame,backgroundColor 和 alpha :
[UIView animateWithDuration:2.0 animations:^{
myView.frame = CGRectMake(50, 200, 200, 200);
myView.backgroundColor = [UIColor blueColor];
myView.alpha = 0.7;
}];
其中有一個比較特殊的 transform 屬性,它的型別是 CGAffineTransform,即 2D 仿射變換,這是個數學中的概念,用一個三維矩陣來表述 2D 圖形的矢量變換,用 transform 屬性對 View 進行:
- 旋轉
- 縮放
- 其他自定義 2D 變換
iOS 提供了下面的函式可以創建簡單的 2D 變換:
CGAffineTransformMakeScaleCGAffineTransformMakeRotationCGAffineTransformMakeTranslation
例如下面的代碼會將 View 縮小至原來的 1/4 大小:
[UIView animateWithDuration:2.0 animations:^{
myView.transform = CGAffineTransformMakeScale(0.5, 0.5);
}];
調節引數
完整版的 animate 函式其實是這樣的:
animateWithDuration:delay:options:animations:completion:
可以通過 delay 引數調節讓影片延遲產生,同時還一個 options 選項可以調節影片進行的方式,可用的 options 可分為兩類:
一、控制程序
例如 UIViewAnimationOptionRepeat 可以讓影片反復進行, UIViewAnimationOptionAllowUserInteraction 可以讓允許用戶對影片進行程序中同 View 進行互動(默認是不允許的)
二、控制速度
影片的進行速度可以用速度曲線來表示(參考這里),提供的選項例如 :
UIViewAnimationOptionCurveEaseIn是先慢后快,UIViewAnimationOptionCurveEaseOut是先快后慢,
不同的選項直接可以通過“與”操作進行合并,同時使用,例如:
UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction
2.2 關鍵幀影片
上面介紹的影片中,我們只能控制開始和結束時的效果,然后由系統補全中間的程序,有些時候我們需要自己設定若干關鍵幀,實作更復雜的影片效果,這時候就需要關鍵幀影片的支持了,下面是一個示例:
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionRepeat | UIViewKeyframeAnimationOptionAutoreverse animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
self.myView.frame = CGRectMake(10, 50, 100, 100);
}];
[UIView addKeyframeWithRelativeStartTime: 0.5 relativeDuration:0.3 animations:^{
self.myView.frame = CGRectMake(20, 100, 100, 100);
}];
[UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:0.2 animations:^{
self.myView.transform = CGAffineTransformMakeScale(0.5, 0.5);
}];
} completion:nil];
這個例子添加了三個關鍵幀,在外面的 animateKeyframesWithDuration 中我們設定了持續時間為 2.0 秒,這是真實意義上的時間,里面的 startTime 和 relativeDuration 都是相對時間,以第一個為例,startTime 為 0.0,relativeTime 為 0.5,這個影片會直接開始,持續時間為 2.0 X 0.5 = 1.0 秒,下面第二個的開始時間是 0.5,正好承接上一個結束,第三個同理,這樣三個影片就變成連續的影片了,
2.3 View 的轉換
iOS 還提供了兩個函式,用于進行兩個 View 之間通過影片換場:
transitionWithView:duration:options:animations:completion:transitionFromView:toView:duration:options:completion:
需要注意的是,換場影片會在這兩個 View 共同的父 View 上進行,在寫影片之前,先要設計好 View 的繼承結構,
同樣,View 之間的轉換也有很多選項可選,例如
UIViewAnimationOptionTransitionFlipFromLeft從左邊翻轉,UIViewAnimationOptionTransitionCrossDissolve漸變等等,
三、CALayer Animation

UIView 的影片簡單易用,但是能實作的效果相對有限,上面介紹的 UIView 的幾種影片方式,實際上是對底層 CALayer 影片的一種封裝,直接使用 CALayer 層的影片方法可以實作更多高級的影片效果,
3.1 基本影片(CABasicAnimation)

CABasicAnimation 用于創建一個 CALayer 上的基本影片效果,下面是一個例子:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];
animation.toValue = https://www.cnblogs.com/reyzhang/p/@200;
animation.duration = 0.8;
animation.repeatCount = 5;
animation.beginTime = CACurrentMediaTime() + 0.5;
animation.fillMode = kCAFillModeRemoved;
[self.myView.layer addAnimation:animation forKey:nil];
KeyPath
這里我們使用了 animationWithKeyPath 這個方法來改變 layer 的屬性,可以使用的屬性有很多,具體可以參考這里和這里,其中很多屬性在前面介紹的 UIView 影片部分我們也看到過,進一步驗證了 UIView 的影片方法是對底層 CALayer 的一種封裝,
需要注意的一點是,上面我們使用了 position 屬性, layer 的這個 position 屬性和 View 的 frame 以及 bounds 屬性都不相同,而是和 Layer 的 anchorPoint有關,可以由下面的公式計算得到:
position.x = frame.origin.x + 0.5 * bounds.size.width;
position.y = frame.origin.y + 0.5 * bounds.size.height;
關于 anchorPoint 和 position 屬性的以及具體計算的原理可以參考這篇文章,
屬性
·CABasicAnimation 的屬性有下面幾個:
beginTimedurationfromValuetoValuebyValuerepeatCountautoreversestimingFunction
可以看到,其中 beginTime,duration,repeatCount 等屬性和上面在 UIView 中使用到的 duration,UIViewAnimationOptionRepeat等選項是相對應的,不過這里的選項能夠提供更多的擴展性,
需要注意的是 fromValue,toValue,byValue 這幾個選項,支持的設定模式有下面幾種:
- 設定
fromValue和toValue:從 fromValue 變化到 toValue - 設定
fromValue和byValue:從 fromValue 變化到 fromValue + byValue - 設定
byValue和toValue:從 toValue - byValue 變化到 toValue - 設定
fromValue: 從 fromValue 變化到屬性當前值 - 設定
toValue:從屬性當前值變化到 toValue - 設定
byValue:從屬性當前值變化到屬性當前值 + toValue
看起來挺復雜,其實概括起來基本就是 :如果某個值不設定,就是用這個屬性當前的值,
另外,可以看到上面我們使用的:
animation.toValue = https://www.cnblogs.com/reyzhang/p/@200;
而不是直接使用 200,因為 toValue 之類的屬性為 id 型別,或者像這樣使用 @ 符號,或者使用:
animation.toValue = https://www.cnblogs.com/reyzhang/p/[NSNumber numberWithInt:200];
最后一個比較有意思的是 timingFunction 屬性,使用這個屬性可以自定義影片的運動曲線(節奏,pacing),系統提供了五種值可以選擇:
kCAMediaTimingFunctionLinear線性影片kCAMediaTimingFunctionEaseIn先快后慢kCAMediaTimingFunctionEaseOut先慢后快kCAMediaTimingFunctionEaseInEaseOut先慢后快再慢kCAMediaTimingFunctionDefault默認,也屬于中間比較快
此外,我們還可以使用 [CAMediaTimingFunction functionWithControlPoints] 方法來自定義運動曲線,這個網站提供了一個將引數調節可視化的效果,關于影片時間系統的具體介紹可以參考這篇文章,
3.2 關鍵幀影片(CAKeyframeAnimation)
同 UIView 中的類似,CALayer 層也提供了關鍵幀影片的支持,CAKeyFrameAnimation 和 CABasicAnimation 都繼承自 CAPropertyAnimation,因此它有具有上面提到的那些屬性,此外,CAKeyFrameAnimation 還有特有的幾個屬性,
values 和 keyTimes
使用 values 和 keyTimes 可以共同確定一個影片的若干關鍵幀,示例代碼如下:
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];//在這里@"transform.rotation"==@"transform.rotation.z"
NSValue *value1 = [NSNumber numberWithFloat:-M_PI/180*4];
NSValue *value2 = [NSNumber numberWithFloat:M_PI/180*4];
NSValue *value3 = [NSNumber numberWithFloat:-M_PI/180*4];
anima.values = @[value1,value2,value3];
// anima.keyTimes = @[@0.0, @0.5, @1.0];
anima.repeatCount = MAXFLOAT;
[_demoView.layer addAnimation:anima forKey:@"shakeAnimation"];
可以看到上面這個影片共有三個關鍵幀,如果沒有指定 keyTimes 則各個關鍵幀會平分整個影片的時間(duration),
path
使用 path 屬性可以設定一個影片的運動路徑,注意 path 只對 CALayer 的 anchorPoint 和position 屬性起作用,另外如果你設定了 path ,那么 values 將被忽略,
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)];
anima.path = path.CGPath;
anima.duration = 2.0f;
[_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
3.3 影片組(CAAnimationGroup)
組影片可以將一組影片組合在一起,所有影片物件可以同時運行,示例代碼如下:
CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
//1.基礎影片一
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animationOne.toValue = https://www.cnblogs.com/reyzhang/p/@2.0;
animationOne.duration = 1.0;
//2.基礎影片二
CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath:@"position.x"];
animationTwo.toValue = https://www.cnblogs.com/reyzhang/p/@400;
animationTwo.duration = 1.0;
[group setAnimations:@[animationOne, animationTwo]];
[self.myView.layer addAnimation:group forKey:nil];
需要注意的是,一個 group 組內的某個影片的持續時間(duration),如果超過了整個組的影片持續時間,那么多出的影片時間將不會被展示,例如一個 group 的持續時間是 5s,而組內一個影片持續時間為 10s ,那么這個 10s 的影片只會展示前 5s ,
3.4 切換影片(CATransition)
CATransition 可以用于 View 或 ViewController 直接的換場影片:
self.myView.backgroundColor = [UIColor blueColor];
CATransition *trans = [CATransition animation];
trans.duration = 1.0;
trans.type = @"push";
[self.myView.layer addAnimation:trans forKey:nil];
// 這句放在下面也可以
// self.myView.backgroundColor = [UIColor blueColor];
為什么改變顏色放在前后都可以呢?具體的解釋可以參考 SO 上的這個回答,簡單來說就是影片和繪制之間并不沖突,
四、后記
如果本文對你有一點幫助的話,歡迎收藏、點贊,感謝,文中如有不對之處,也歡迎大家在評論區指出,共勉,
本文來自博客園,作者:reyzhang,轉載請注明原文鏈接:https://www.cnblogs.com/reyzhang/p/16645372.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/503440.html
標籤:iOS
