老司機帶你走進Core Animation

AmeeLigon 8年前發布 | 7K 次閱讀 iOS開發 移動開發 Core Animation

老司機帶你走進Core Animation

 

老司機帶你走進Core Animation

事實上,老司機今天講的只是核心動畫(Core Animation)中的一小部分, 動畫那部分。

開發中,有的時候我們可愛的UI妹子或者產品妹子會說(表示一下純屬個人YY):技術哥哥,這里能不能duang的一下彈出來呢?這里能不能轉個圈出現啊?這里能不能加一些炫酷的效果啊?

Duang

作為 高冷而又無所不能 的技術,能說不么?

不能!

然后你就硬著頭皮去寫動畫吧。

好在呢,蘋果已經想到 程序員也是要撩妹 的這個需求,所以為我們提供了CAAnimation這個好東西,當然還貼心的幫我們又進行了一層 封裝 ,那就是 UIView得animate相關 的方法了。

然而封裝好的東西,靈活度當然會降低了。所以既然是基于 CAAnimation 的,那我們就去自己調用好了!

所以呢,今天我打算說說CAAnimaiton。

這篇可能會涉及到什么呢?

  • CALayer與UIView
  • CAAnimation與UIView animate

CALayer

為什么會先說CALayer呢?以為 CAAimation實際上操作的都是Layer層 。

所以不知道CALayer會很頭疼的,知道的偷學去沖杯咖啡吧。

The CALayer class manages image-based content and allows you to perform animations on that content. Layers are often used to provide the backing store for views but can also be used without a view to display content. A layer’s main job is to manage the visual content that you provide but the layer itself has visual attributes that can be set, such as a background color, border, and shadow. In addition to managing visual content, the layer also maintains information about the geometry of its content (such as its position, size, and transform) that is used to present that content onscreen. Modifying the properties of the layer is how you initiate animations on the layer’s content or geometry. A layer object encapsulates the duration and pacing of a layer and its animations by adopting the CAMediaTiming protocol, which defines the layer’s timing information.

If the layer object was created by a view, the view typically assigns itself as the layer’s delegate automatically, and you should not change that relationship. For layers you create yourself, you can assign a delegate object and use that object to provide the contents of the layer dynamically and perform other tasks. A layer may also have a layout manager object (assigned to the layoutManager property) to manage the layout of subviews separately.

這是官方文檔對CALayer的解釋,以老司機的英語水平翻譯成人話就是:

CALayer是用來 繪制、渲染 圖形的。

那他與UIView又有什么區別和聯系呢?

事實上所有的UIView及其子類圖形的繪制。UIView下有一個layer屬性,這個layer層就是真正繪制UIView所要展示的東西的人。然而之所以要將CALayer封裝成UIView則是為了給其 添加事件響應 。

因為 CALayer 是繼承與NSObject的,所以他是 不具備響應 的。而 UIView是繼承與UIResponder 的,UIResponder本身 可以提供事件響應 ,再用CALayer給他繪制一個圖像,那一個具有響應事件的對象就誕生了,他就是我們的UIView。

當我們創建一個UIView對象時,系統自動為我們創建一個CALayer對象,這個對象就是UIView的layer屬性。

CALayer有具體有什么屬性呢?

前面有說過,layer層負責繪制和渲染,那么圖像的基本屬性他是一定要有的。

這里呢,老司機還是著重介紹一個常用和重要的屬性吧。

CALayer有 bounds,position,frame 的屬性,他呢,其實就是UIView中bounds,center,frame的映射。事實上,我們在layer中一般只操作bounds和position兩個屬性。由于有著對應關系,所以這個理解起來就相對容易,我就不展開講解了。

CALayer還有一個非常重要的屬性 anchorPoint ,即錨點。說起來這個概念還是真難解釋,錨點就好像是體心,一個物體抽象成一個點的對象。還記得物理中的質點么?我們操作屬性,比如移動,旋轉,縮放等等都是以錨點作為 參考點 的。他是一個 CGPoint類型 的對象,他的 x、y取值范圍都是0~1 。數值就是從錨點到layer的左上角(類比UIView的origin)的 橫向/縱向 距離占layer得 width/height 的 比例 。

錨點

contents ,寄宿圖。事實上這個屬性我們操作的也很少,不過還是可以解釋一下的。他可以看做是 當前圖層的背景圖片 。就是在當前圖層的背景展示一張圖片。也就是說你甚至可以用一個UIView展示一張圖片了,就是這樣。不過你別看他的類型是id,可不代表你給他傳什么對象都可以。事實上你只能傳 CGImageRef 類型的數據進去。他的id類型是為了配合OS X系統的。哦,你說為什么不能傳UIIamge?是這樣的, CALayer是在QuartzCore框架下 的,他是可以跨平臺的,也就是在iOS和OS X上都可以,所以他當然不能讓你傳入UIKit下的對象了。 CALayer的所有屬性都不能傳入UIKit的對象 。

transform ,仿射變換啦,這個東西其實挺多能講的,那套圖像變換的原理挺有意思的,不過我矩陣真的不會算了=。=延展的東西數學好的同學們自己看吧,其實想用還是挺簡單的。

cornerRadius、masksToBounds 。這兩個屬性比較常用啦,切圓角時候我們用的屬性。

opacity ,類比UIView的alpha。

shadowOpacity、shadowColor、shadowPath、shadowOffset、shadowRadius ,這幾個陰影相關的屬性。這里需要注意的是 shadowOpacity的默認值現在是0 。也就是說默認效果下你是看不到任何陰影效果的,想要實現陰影想過請先 更改shadowOpacity為一個非0得小于等于1的值 。還有一點就是由于shadow是圖層外的延展效果,要想看到shadow效果請 設置masksToBounds屬性為No 。

borderColor、borderWidth ,這是邊框相關的屬性。borderWidth默認值是0。

mask ,這也是個有趣又有用的屬性, 遮罩屬性 。可以以一個layerA作為另一個layerB的遮罩,即layerB.mask = layerA。那么作為遮罩的layerA中的透明區域將被過濾掉, layerB只顯示layerA的非透明區域 。借助這個屬性可以實現很多神奇的效果,比如歌詞、圖像展開等等。

mask

CALayer還有一個其他的屬性,不過平時使用的也不多,老司機就不逐一介紹了,有興趣的同學可以自行了解哈。

基于CALayer的種種屬性,以及CALayer還有很多子類,有了他們,我們能看到各種各樣的UI控件,那我們又如何創建動畫呢?

CAAnimation

CAAnimation是什么呢?

CAAnimation is an abstract animation class. It provides the basic support for the CAMediaTiming and CAAction protocols. To animate Core Animation layers or Scene Kit objects, create instances of the concrete subclasses CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, or CATransition.

官方對CAAnimation的描述也并不多,其實不過說的的確都很到位。

CAAniamtion是一個 抽象類 ,遵循著CAMediaTiming和CAAciotn兩個協議。通過他的 4個子類 ,我們可以 實現很多絢麗的動畫效果 。

CAAnimation下有幾個屬性,下面逐一介紹

timingFunction ,這個呢,指定的是動畫的節奏。所謂節奏是什么什么意思呢?就是動畫執行的快慢交替。有如下幾個可選項

  • kCAMediaTimingFunctionLinear//線性節奏,就是勻速
  • kCAMediaTimingFunctionEaseIn//淡入,緩慢加速進入,然后勻速
  • kCAMediaTimingFunctionEaseOut//淡出,勻速,然后緩慢減速移除
  • kCAMediaTimingFunctionEaseInEaseOut//淡入淡出,結合以上兩者
  • kCAMediaTimingFunctionDefault//默認效果

delegate ,代理。設置代理以后就會執行代理方法啦。

  • -(void)animationDidStart:(CAAnimation *)anim;

  • -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

一個是動畫開始的代理,一個是動畫結束的代理。

值得注意的是,結束代理中,有一個flag。他的意思是如果動畫正常播放完成的話,flag為YES。如果沒有播放完成或者被移除則返回NO。

removedOnCompletion ,是否在播放完成后移除。這是一個非常重要的屬性,有的時候我們希望動畫播放完成,但是保留最終的播放效果是,這個屬性一定要改為NO,否則無效。

遵循著CAMediaTiming協議,所以他自然也有duration、beginTime等一些屬性。

beginTime ,動畫的開始時間,準確的說應該叫滯后時間。就是當你將動畫加載layer中后滯后多長時間開始播放。

/* The begin time of the object, in relation to its parent object, if

  • applicable. Defaults to 0. */

這個屬性很重要,我想要著重講一下。上面是beginTime屬性的注釋。從中我們能夠看出,這個 beginTime是與父對象有關 的。

由于CALayer和CAAnimation都遵循CAMediaTiming協議,所以那他都可以作為我們animation對象的父對象。

如果你將animation添加在一個動畫組(CAAnimationGroup)中,那么ok,你直接按照下面的寫法就好了。

animation.beginTime = beginTime;

但是,如果你直接添加在一個layer上

他的父對象是layer。這個layer的時間線很可能是一個過去的時間。即使你添加上beginTime得到的仍舊是一個過去的時間。那么這個時候我們的動畫就會顯示在動畫結束時的狀態。為了避免這種狀況,我們要修正我們的時間。代碼如下:

CFTimeInterval time = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
animation.beginTime = time + beginTime;

CACurrentMediaTime()是馬赫時間,是全局時間,也就是設備距離上次開機的時間。

convertTime是獲取本地時間。該方法有兩個參數,第一個是時間,第二個是時間所對應的圖層。當第二個參數為nil時,則返回的就是第一個參數的值。

這樣我們就能得到一個絕對時間。

這里很重要,不過引申下去就遠了,想了解的同學點 這里

duration ,是動畫的持續時間。簡單的概念我就一筆帶過了吧,同樣的還有 repeatCount,autoreverses 。這些都是一些基本屬性,基本看單詞就知道用途了。

duration

speed ,這個我也要說一下,他表示的是 當前對象的時間流速 。簡單來說,如果speed是2,duration是3,那么經過1.5秒,我的動畫已經播放完成了。s = v * t,s就相當于已經播放的動畫,也就是長度為3個單位的動畫,v相當于每秒播放多少動畫,即每秒播放兩個單位的動畫,所以1.5秒后動畫其實就播放完成了。

speed

timeOffset ,是表示我將從動畫的 第幾秒開始播放 。比如一個duration = 3的動畫,timeOffset = 2,那么此時我的動畫從第二秒開始播放,播放到第三秒動畫結束的狀態后,立即變為動畫的初始狀態,也就是第0秒的播放狀態,繼續播放之第二秒的狀態,然后動畫結束。形象的說就好像你繞操場跑圈,以前你都是 從起點開始跑跑一圈 ;這回你 從一半開始跑 ,但是 同樣跑一圈 ,過了起點就還要再跑半圈,就是這樣。

timeOffset

fillMode,是播放結束后的狀態。他有四個枚舉值

  • kCAFillModeForwards//保持結束時狀態
  • kCAFillModeBackwards//保持開始時狀態
  • kCAFillModeBoth//保持兩者,我沒懂兩者是什么概念,實際使用中 與kCAFillModeBackwards相同
  • kCAFillModeRemoved//移除

哦,這個屬性使用的時候要設置 removedOnCompletion = NO ,否則你是看不到效果的。其實除了保持結束狀態有效果,其他跟沒效果也沒什么區別。。可能也是我沒看出來。。

其實說實話,我也不想講這么些屬性,不過這些鋪墊也不好講。

下面又到了我們最喜歡的淘寶推薦環節。不對,是代碼環節。

CABasicAnimation

前文說過,CAAnimation是一個抽象類,想要實現動畫效果呢,是要使用其四個子類的。

首先我們就介紹一下CABasicAnimation。

看名字就知道,這是一個多么基礎的動畫啊=。=

CABasicAnimation用來 創建基于兩個狀態的動畫 ,你只需要給出兩個狀態,一個初始狀態一個終止狀態,系統自動為你將中間的動畫補全。

UIView * redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
CABasicAnimation * animaiton = [CABasicAnimation animationWithKeyPath:@"position"];
animaiton.removedOnCompletion = NO;
animaiton.fillMode = kCAFillModeForwards;
animaiton.duration = 2;
animaiton.toValue = [NSValue valueWithCGPoint:CGPointMake(400, 400)];
[redView.layer addAnimation:animaiton forKey:nil];

移動

這已經是最簡單的一個動畫效果了。(無視起點位置不對=。=視頻錄制時機總是晚)

下面老司機逐句講解一下。

首先呢,我創建了一個animation對象。那個 keyPath 是什么呢?是我們要修改的屬性名。那,我們要給誰做動畫?老司機說過,CAAnimation都是對CALayer進行展示動畫的。所以這屬性當然是 CALayer的屬性 了。至于那些屬性改變支持動畫效果呢?command + 左鍵點進CALayer,我們能看到CALayer的每個屬性。看他的注釋,是不是最后一句有一個 animatable 。對了,有這個的, 就是支持動畫 的。

支持動畫的屬性

接下來的三句有了上面的介紹就應該很清楚了,分別是完成時不移除,完成時保持末尾狀態,播放時長2秒。

再往下看,我 給animation的toValue賦值 。

這是在做什么呢?不知道,我們就點進去看看。

這個看到有 toValue,fromValue,byValue 。

注釋還挺多,分開看。老司機之前說過, CABasicAnimation是要指定動畫的初始狀態和終止狀態的 。那這三個屬性就是用來指定狀態的。

  • from就是指定初始狀態
  • toValue就是終止狀態
  • by就是狀態的增量

這三個值呢, 不能全為空 ,以為這樣你就一個狀態也沒有指定。

也不能全不為空 ,因為這樣你就指定了三個狀態,系統也不知道選哪兩個。

若果你 指定了一個狀態 ,那系統將自動 以當前狀態作為另一個狀態 。

若你 指定了兩個狀態 ,則系統 已這兩個狀態作為始末狀態 。

還有一點要說的是,看屬性也看的出來,這個value你是要 傳入一個對象 的,所以老司機將CGPoint裝在了一個NSValue中。

最后一句就是將動畫填入layer中了,注意這里老司機圖省事就沒有給key。實際開發中 建議開發者填寫key且key不可重復 ,因為如果涉及到檢測動畫播放進度或者是移除動畫之類的都要填寫正確的key才可以。

好的,我們的動畫已經初具規模了,我們一點一點完善。

CABasicAnimation * animaiton = [CABasicAnimation animationWithKeyPath:@"position"];
animaiton.removedOnCompletion = NO;
animaiton.fillMode = kCAFillModeForwards;
animaiton.duration = 2;
animaiton.beginTime = CACurrentMediaTime() + 1;
animaiton.repeatCount = MAXFLOAT;
animaiton.toValue = [NSValue valueWithCGPoint:CGPointMake(400, 400)];
[redView.layer addAnimation:animaiton forKey:nil];

代碼改成了這個樣子,跑一下看看是什么樣子。

延時

我們看到我添加這延時語句,同時改變了repeatCount讓他無限循環。(這里你要注意我延時語句的寫法)

我們再稍微改一下

CABasicAnimation * animaiton = [CABasicAnimation animationWithKeyPath:@"position"];
animaiton.removedOnCompletion = NO;
animaiton.fillMode = kCAFillModeForwards;
animaiton.duration = 2;
animaiton.toValue = [NSValue valueWithCGPoint:CGPointMake(400, 400)];
[redView.layer addAnimation:animaiton forKey:nil];
animaiton.beginTime = CACurrentMediaTime() + 1;
animaiton.repeatCount = MAXFLOAT;

發現變化了么?老司機把重復和延時放在了添加動畫之后,這個時候動畫是什么樣子的呢?

調整語句順序

延時沒有了,也不重復了,怎么回事???

因為當你調用addAnimation:forKey:這句時,其實系統是對你傳入的 animation進行了一次copy ,然后 把copy的這份添加在圖層上 。這時你再改animation當然是不能更改動畫效果的了。

這里同時也引出了一點,當你將animation加入layer層以后,你就無法再更改動畫效果了。

其他的屬性都是字面意思,老司機就不一句一句講了。

CAKeyframeAnimation

剛才也忘了說了,其實CABasicAnimation和CAKeyframeAnimation都是繼承自CAPropertyAnimation。看名字就知道是根據屬性來展示動畫的。

所以CAKeyframeAnimation也是根據屬性展示動畫的,他與CABasicAnimation的不同點在于他可以 指定多個狀態 ,不局限于始末狀態,這樣 你的動畫將更加靈活。

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[redView.layer addAnimation:animation forKey:@"keyframe"];

keyframe

還是逐句講一下。

我先生成一個CAKeyframeAnimation對象,指定要做動畫的屬性。

然后 給values屬性給了一個數組 。這什么意思呢? CABasicAnimation是指定兩個狀態,而我們的CAKeyframeAnimation則是指定多個狀態 ,動畫也的確按照我的規劃移動了。

其實這里你應該注意到一點,有沒有發現我的紅色方形最開始是看不到全部的?因為還記得 錨點 那個概念么?他的初始值是CGPointMake(0.5,0.5), 所有動畫都是以錨點為參考點 ,所以說你指定的狀態都是相對于錨點來說的狀態。當然如果有需要,你可以修改錨點來實現一些特殊的動畫效果。

改一下代碼

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.calculationMode = kCAAnimationCubicPaced;
[redView.layer addAnimation:animation forKey:@"keyframe"];

calculationMode

我改變了 calculationMode 這個屬性,有沒有發現轉折點出動作平滑了許多?恩,這個屬性是用來改變補間動畫的計算模式的。這個屬性 是CAKeyframeAnimation獨有的屬性 。

繼續修改

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.keyTimes = @[@0,@0.8,@1];
[redView.layer addAnimation:animation forKey:@"keyframe"];

我去掉了calculationMode屬性,添加了keyTimes屬性,效果是這樣的。

keyTimes

是不是發現第一段路徑速度明顯比第二段慢?是因為 keyTimes屬性指定的是當前狀態節點到初始狀態節點的時間占動畫總時長的比例 。若果 不設置keyTimes則勻速播放 。

Go on

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.keyTimes = @[@0,@0.8,@1];
animation.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)].CGPath;
[redView.layer addAnimation:animation forKey:@"keyframe"];

path

這回機智如你應該發現幾個問題,第一路徑變了。

因為我們 指定了path屬性 ,所以這時 values屬性將被忽略 ,按照指定的path運動。(此處注意我給的是CGPathRef類型數據,為什么?還記得之前說的UIKit的事么?)

第二,即使以path為運動給你好像也不太對?

這是因為以path為運動軌跡后只是相當于用另一種方式填寫了values屬性。這是一個圓形的路徑,他被分成了四個 子路徑 。然而你在keyTimes中指定的時間狀態只有第二個 狀態到初始狀態的時間比例為1,自然后面的動畫就沒有了。

改成下面的樣子就好了。

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.keyTimes = @[@0,@0.25,@0.5,@0.75,@1];
animation.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)].CGPath;
[redView.layer addAnimation:animation forKey:@"keyframe"];

修改keyTimes

以上就是基于CAPropertyAnimation的屬性動畫的基本使用方法,當然這里老司機一直使用移動動畫做的示例,你可以 更改屬性,去做其他的動畫都是可以的 。另外溫馨提示, 二級屬性也可以哦 。

那你可能要說了,我使用過程中一般不可能只改變一個屬性啊,我想兩個一起改變怎么辦啊?

我們的衣食父母蘋果怎么會沒想到呢?所以他為我們提供了一個類,CAAnimationGroup。

CAAnimationGroup

看名字就看得出來是動畫組了,他支持多個動畫并發執行。

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.values = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],[NSValue valueWithCGPoint:CGPointMake(100, 100)],[NSValue valueWithCGPoint:CGPointMake(0, 200)]];
animation.duration = 2;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.keyTimes = @[@0,@0.25,@0.5,@0.75,@1];
animation.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)].CGPath;

CABasicAnimation * animation2 = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
animation2.toValue = @50;
animation2.duration = 2;
animation2.fillMode = kCAFillModeForwards;
animation2.removedOnCompletion = NO;

CAAnimationGroup * group = [CAAnimationGroup animation];
group.duration = 2;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.animations = @[animation,animation2];

[redView.layer addAnimation:group forKey:@"group"];

CAAnimationGroup

其實用法差不多,不同是的首先我 不需要指定屬性 了,因為CAAnimationGroup可以播放多個屬性同時變化,所以不需要指定屬性。

其次 不需要指定狀態了 。因為CAAnimationGroup相當于多個CAAnimation動畫并發執行的管理者,本身狀態取決于其子動畫的狀態。

還有一個animations屬性,這個屬性用于指定他的子動畫。這個屬性有些兩點,可以說一下。我們點進去可以看到,animations是 裝有CAAnimation對象一個的數組 。這句話的重點就是CAAnimationGroup也繼承與CAAnimation,所以 CAAnimationGroup是可以嵌套 的。

animations

記得之前我說過beginTime很重要么?記得那個屬性要加上矯正值么?想在你完全不用考慮那個問題了。遇到要改變beginTime的動畫, 直接把他丟到CAAnimationGroup里面 去,然后時間你就直接加吧,也不用矯正了,哈哈哈哈、

CAAnimationGroup是個好東西,簡化了很多操作,同時還可以嵌套,屬性還很少。

支持并發動畫演示,屌屌的。

CATransition

最后一個啦,轉場動畫。

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton * bu = [UIButton buttonWithType:(UIButtonTypeSystem)];
    [bu setBackgroundColor:[UIColor yellowColor]];
    [bu setFrame:CGRectMake(200, 200, 100, 100)];
    [self.view addSubview:bu];
    [bu addTarget:self action:@selector(a:) forControlEvents:(UIControlEventTouchUpInside)];
    self.view.backgroundColor = [UIColor grayColor];
    UIImageView * redView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    redView.backgroundColor = [UIColor redColor];
    redView.image = [UIImage imageNamed:@"2.jpeg"];
    [self.view addSubview:redView];
    self.imgV = redView;    
}
-(void)a:(UIButton *)btn
{
    CATransition *animation = [CATransition animation];
    animation.duration = 5;
    animation.fillMode = kCAFillModeForwards;
    animation.type = @"rippleEffect";
    animation.subtype = kCATransitionFromTop;
    [self.imgV.layer addAnimation:animation forKey:@"ripple"];
    self.imgV.image = [UIImage imageNamed:@"3.jpg"];
}

transition

看到了沒有這個水波效果還是挺炫的。

這個動畫有兩點不同,一個是 type ,這個屬性指定的是動畫的主類型,有以下幾種可選擇的動畫:

  • kCATransitionFade
  • kCATransitionMoveIn
  • kCATransitionPush
  • kCATransitionReveal

還有一些系統私有的動畫但是可以安全使用,但是你只能用字符串

//@"cube" @"moveIn" @"reveal" @"fade"(default) @"pageCurl" @"pageUnCurl" @"suckEffect" @"rippleEffect" @"oglFlip"

還有一些絕對不能使用的動畫我就不放出來了

另外一個屬性是subType。

有四種選項:

  • kCATransitionFromRight
  • kCATransitionFromLeft
  • kCATransitionFromTop
  • kCATransitionFromBottom

見名知意,就是指動畫的方向啦。

不過呢,這個轉場動畫不好的一點是需要跟轉場代碼寫在一起,然而官方又沒有給出轉場到底是什么概念。

所以我目前測出來的能用的情況有, imageView切換圖片 , 控制器的push或modal , UIView對象調用exchangeSubviewAtIndex:WithIndex:方法 的時候可以出發轉場動畫,其他我真是沒有測出來,有大神知道還望告知=。=十分感謝。

以上呢,就是CAAnimation的基本使用方法,基于這個你還可以自己組合出很多絢麗的動畫,老司機就不在在這賣弄了。

哦,老司機剛才說了,老司機寫CoreAnimation的教程是有陰謀的,陰謀是什么呢?嘿嘿嘿~

好多動畫在一起

吶,這是一個老司機封裝的DWAnimation,他可以輕松、優雅地幫助你生成上面的動畫。(有些動畫播放兩次是因為demo中要展示某些屬性的用處,不要在意)

比如這樣:

優雅么?

 

參考資料:

 

來自:http://www.jianshu.com/p/92a0661a21c6

 

 本文由用戶 AmeeLigon 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!