自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

【實(shí)例教程】你會(huì)用swift創(chuàng)建復(fù)雜的加載動(dòng)畫嗎

移動(dòng)開發(fā)
時(shí)至今日,iOS 應(yīng)用商店已經(jīng)擁有超過(guò)了140萬(wàn) 應(yīng)用,讓你自己的應(yīng)用脫穎而出確實(shí)是個(gè)不小的挑戰(zhàn)。不過(guò),在你的應(yīng)用掉入默默無(wú)聞的大黑洞之前,你擁有一個(gè)小小的機(jī)遇窗,它能幫你吸引用戶的注意。

[[147928]]

時(shí)至今日,iOS 應(yīng)用商店已經(jīng)擁有超過(guò)了140萬(wàn) 應(yīng)用,讓你自己的應(yīng)用脫穎而出確實(shí)是個(gè)不小的挑戰(zhàn)。不過(guò),在你的應(yīng)用掉入默默無(wú)聞的大黑洞之前,你擁有一個(gè)小小的機(jī)遇窗,它能幫你吸引用戶的注意。

想讓你的用戶喝彩尖叫,沒(méi)有比應(yīng)用加載界面更好的地方 ,在這個(gè)地方,你可以添加一個(gè)討人喜歡的動(dòng)畫來(lái)作為你登陸或者認(rèn)證流程的先導(dǎo)。

在這個(gè)教程中,你將要學(xué)會(huì)如何利用先進(jìn)的技術(shù)來(lái)創(chuàng)建一個(gè)流暢并且迷人的動(dòng)畫。

開始吧??!

從這里下載啟動(dòng)項(xiàng)目,保存在一個(gè)合適的路徑并用Xcode打開。

打開 HolderView.swift 。 在這個(gè)UIView 的子類中,你可以添加些子層(在Layers的下級(jí)目錄中可以找到),使之像上面的動(dòng)畫一樣生動(dòng)

OvalLayer.swift: 這是第一層,它從零尺寸擴(kuò)展,然后會(huì)有一小段時(shí)間的搖擺

TriangleLayer.swift: 接下來(lái)的這個(gè)層TriangleLayer會(huì)在OvalLayer 搖擺的時(shí)候出現(xiàn),當(dāng)此視圖轉(zhuǎn)動(dòng)時(shí),OvalLayer 會(huì)縮小到零尺寸,并在TriangleLayer 中消失。

RectangleLayer.swift: 這個(gè)層是TriangleLayer 用于分類的可視化容器

ArcLayer.swift: 這個(gè)層動(dòng)畫特效填充在RectangleLayer 中,這和杯子里填充了水(效果)非常相似

打開OvalLayer.swift, 啟動(dòng)項(xiàng)目已經(jīng)包含了用于初始化這個(gè)層的代碼和所有你會(huì)在動(dòng)畫里用到的Bezier path(對(duì)象)。你會(huì)看到expand(),wobble()和contract()方法都是空的。你可以通過(guò)參考這個(gè)指導(dǎo)書來(lái)填充這些方法。所有其他的 *Layer (以layer結(jié)尾)的文件都用了相似的方式構(gòu)建。

注意:如果你想要學(xué)習(xí)更多的Bezier paths,那就檢出我們系列指導(dǎo)書 Modern Core Graphics with Swift

最后,打開ViewController.swift 查看addHolderView()方法,這個(gè)方法添加了一個(gè)HolderView 作為一個(gè)子視圖,放到viewcontroller 視圖的中間。這個(gè)視圖將會(huì)放置所有的動(dòng)畫。viewcontroller僅僅需要把它放到屏幕上,這個(gè)視圖將會(huì)照管好現(xiàn)行的動(dòng)畫代碼。

animateLabel() 是由類 HolderView 提供的代理回調(diào)函數(shù),此類中你會(huì)用你完成的動(dòng)畫序列來(lái)填充。addButton()方法只是添加一個(gè)按鈕到視圖中,用于觸摸和重啟動(dòng)畫。

編譯并運(yùn)行你的應(yīng)用;你會(huì)看到一個(gè)空白屏幕。一個(gè)空白的畫布--這就是用于開始創(chuàng)建你的新動(dòng)畫的完美的載體。在指導(dǎo)書的最后,你的應(yīng)用會(huì)看起來(lái)是這樣的:

08.gif

現(xiàn)在不需再費(fèi)周折,我們開始吧

添加一個(gè)橢圓

這個(gè)動(dòng)畫從一個(gè)橢圓開始,橢圓是從屏幕中間擴(kuò)展到視圖,然后在周圍有點(diǎn)搖擺。

打開 HolderView.swift ,在 HolderView 類的頂端附近聲明如下的常量

  1. let ovalLayer = OvalLayer() 

現(xiàn)在在此類的底部添加如下方法

  1. func addOval() { 
  2.   layer.addSublayer(ovalLayer) 
  3.   ovalLayer.expand() 

這段代碼首先添加了你上面創(chuàng)建的 OverLayer 的實(shí)例作為一個(gè)子層到視圖層,然后調(diào)用 expand() 方法,這是被切掉的需要你來(lái)填充的函數(shù)之一

來(lái)到 OvalLayer.swift 文件,添加如下代碼到 expand() 中:

  1. func expand() { 
  2.   var expandAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path"
  3.   expandAnimation.fromValue = ovalPathSmall.CGPath 
  4.   expandAnimation.toValue = ovalPathLarge.CGPath 
  5.   expandAnimation.duration = animationDuration 
  6.   expandAnimation.fillMode = kCAFillModeForwards 
  7.   expandAnimation.removedOnCompletion = false 
  8.   addAnimation(expandAnimation, forKey: nil) 

這個(gè)函數(shù)創(chuàng)建了一個(gè) CABasicAnimation 的實(shí)例,這個(gè)實(shí)例用于改變橢圓從 ovalPathLarge.到 ovalPathSmall 的路徑。啟動(dòng)項(xiàng)目為你提供了兩者的Bezier paths。

設(shè)置動(dòng)畫的 removedOnCompletion 的值為 false,fillMode 的值為 KCAFillModeForwards ,使得當(dāng)動(dòng)畫結(jié)束的時(shí)候,橢圓保留它新的路徑。

最后,打開 ViewController.swift ,在 view.addSubview(holderView) 下的 addHolderView() 方法中添加如下的線條


  1. holderView.addOval() 

將 holdview 添加到 ViewController 的視圖中后,調(diào)用 addOval 方法來(lái)啟動(dòng)動(dòng)畫

構(gòu)建并運(yùn)行你的應(yīng)用,你的動(dòng)畫現(xiàn)在就會(huì)看起來(lái)像下面(圖例)

09.gif

搖動(dòng)橢圓

使用視圖中擴(kuò)張的橢圓,下一步就是在橢圓的步調(diào)中設(shè)置一些反彈,使之搖擺起來(lái)

打開 HolderView.swift,在此類的底部,添加下面的函數(shù)

  1. func wobbleOval() { 
  2.   ovalLayer.wobble() 

在 OvalLayer 中調(diào)用被切掉的方法 wobble().

現(xiàn)在打開 OverLayer.swift,在 wobble() 中添加如下代碼


  1. func wobble() { 
  2.   // 1 
  3.   var wobbleAnimation1: CABasicAnimation = CABasicAnimation(keyPath: "path"
  4.   wobbleAnimation1.fromValue = ovalPathLarge.CGPath 
  5.   wobbleAnimation1.toValue = ovalPathSquishVertical.CGPath 
  6.   wobbleAnimation1.beginTime = 0.0 
  7.   wobbleAnimation1.duration = animationDuration 
  8.   
  9.   // 2 
  10.   var wobbleAnimation2: CABasicAnimation = CABasicAnimation(keyPath: "path"
  11.   wobbleAnimation2.fromValue = ovalPathSquishVertical.CGPath 
  12.   wobbleAnimation2.toValue = ovalPathSquishHorizontal.CGPath 
  13.   wobbleAnimation2.beginTime = wobbleAnimation1.beginTime + wobbleAnimation1.duration 
  14.   wobbleAnimation2.duration = animationDuration 
  15.   
  16.   // 3 
  17.   var wobbleAnimation3: CABasicAnimation = CABasicAnimation(keyPath: "path"
  18.   wobbleAnimation3.fromValue = ovalPathSquishHorizontal.CGPath 
  19.   wobbleAnimation3.toValue = ovalPathSquishVertical.CGPath 
  20.   wobbleAnimation3.beginTime = wobbleAnimation2.beginTime + wobbleAnimation2.duration 
  21.   wobbleAnimation3.duration = animationDuration 
  22.   
  23.   // 4 
  24.   var wobbleAnimation4: CABasicAnimation = CABasicAnimation(keyPath: "path"
  25.   wobbleAnimation4.fromValue = ovalPathSquishVertical.CGPath 
  26.   wobbleAnimation4.toValue = ovalPathLarge.CGPath 
  27.   wobbleAnimation4.beginTime = wobbleAnimation3.beginTime + wobbleAnimation3.duration 
  28.   wobbleAnimation4.duration = animationDuration 
  29.   
  30.   // 5 
  31.   var wobbleAnimationGroup: CAAnimationGroup = CAAnimationGroup() 
  32.   wobbleAnimationGroup.animations = [wobbleAnimation1, wobbleAnimation2, wobbleAnimation3,  
  33.      wobbleAnimation4] 
  34.   wobbleAnimationGroup.duration = wobbleAnimation4.beginTime + wobbleAnimation4.duration 
  35.   wobbleAnimationGroup.repeatCount = 2 
  36.   addAnimation(wobbleAnimationGroup, forKey: nil) 

代碼真夠多的。但斷句還是很講究的。 接下來(lái)要做的是:

  1. 從大路徑下降到被垂直壓扁的動(dòng)畫
  2. 從垂直壓扁變成水平和垂直都?jí)罕?/li>
  3. 和垂直擠壓(動(dòng)畫)切換
  4. 回到大路徑結(jié)束動(dòng)畫
  5. 把你所有的動(dòng)畫合并到CAAnimationGroup組,并把這個(gè)動(dòng)畫組添加到你的 OvalLayout 中。

每一個(gè)隨后的動(dòng)畫的 beginTime 都是其前一個(gè)動(dòng)畫和動(dòng)畫持續(xù)時(shí)間的 beginTime 總和。你重復(fù)動(dòng)畫組兩次就會(huì)給你一種擺動(dòng)出稍微拉長(zhǎng)的感覺(jué)

#p#

盡管你現(xiàn)在擁有產(chǎn)生搖擺動(dòng)畫的所有代碼,你還是不能調(diào)用你的新動(dòng)畫

我們回到 HolderView.swift,在 addOval() 結(jié)尾處添加如下代碼


  1. NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "wobbleOval"
  2.                           userInfo: nil, repeats: false

在這里,你創(chuàng)建了一個(gè)timer定時(shí)器,它會(huì)在OvalLayer已經(jīng)結(jié)束擴(kuò)張后調(diào)用 wobbleOval()

編譯并運(yùn)行你的應(yīng)用,檢查下你的新動(dòng)畫。

這有點(diǎn)微妙,但那對(duì)一個(gè)真正的明快的動(dòng)畫是一個(gè)重要的因素。你不再需要那些滿屏幕都是亂飛的東西了。

10.gif

開始變身

是時(shí)候來(lái)電有趣的東西了。你將要把一個(gè)橢圓變身成為一個(gè)三角形。在用戶眼里,這個(gè)轉(zhuǎn)變應(yīng)該看上去無(wú)縫連接的。要做到這些,你會(huì)用到兩個(gè)相同顏色的分離的形狀。

打開HolderView.swift,在HolderView類的頂端稍微靠近你早些時(shí)候添加的 OvalLayer 屬性的下面添加如下代碼


  1. let triangleLayer = TriangleLayer() 

這里聲明了一個(gè) TriangleLayer 類的常量,正如你在 OvalLayer 中做的一樣

現(xiàn)在,讓wobbleOval()方法看上去像這樣:


  1. func wobbleOval() { 
  2.   // 1 
  3.   layer.addSublayer(triangleLayer) // Add this line 
  4.   ovalLayer.wobble() 
  5.   
  6.   // 2   
  7.   // Add the code below 
  8.   NSTimer.scheduledTimerWithTimeInterval(0.9, target: self,  
  9.                                          selector: "drawAnimatedTriangle", userInfo: nil,  
  10.                                          repeats: false)  

上面的代碼做了如下這些事情:

  1. 這行(代碼)添加了一個(gè) TiangleLayer 實(shí)例,這個(gè)實(shí)例在稍早的時(shí)候作為HolderView層的子層已經(jīng)被初始化過(guò)了。

  2. 正如你所知道的,因?yàn)檫@個(gè)搖擺動(dòng)畫在1.8s的總間隔時(shí)間內(nèi)運(yùn)行兩次,所以在中間點(diǎn)啟動(dòng)變形過(guò)程會(huì)是一個(gè)非常好的地方。因此,你要添加一個(gè)定時(shí)器timer,它在延遲0.9s之后執(zhí)行drawAnimatedTriangle()

注意:找到動(dòng)畫的正確的間隔或延遲需要反復(fù)實(shí)驗(yàn),這也是一個(gè)好的動(dòng)畫和一個(gè)極好的動(dòng)畫區(qū)別。我鼓勵(lì)你去修補(bǔ)你的動(dòng)畫,讓它們看上去完美。這可能要花點(diǎn)時(shí)間,但確是值得的。

接下來(lái),在此類的底部添加如下的函數(shù)。


  1. func drawAnimatedTriangle() { 
  2.   triangleLayer.animate() 

這個(gè)方法會(huì)被你剛剛加入到 wobbleOval() 中的timer定時(shí)器調(diào)用。

現(xiàn)在打開 TriangleLayer.swift,添加如下代碼到 animate()


  1. func animate() { 
  2.   var triangleAnimationLeft: CABasicAnimation = CABasicAnimation(keyPath: "path"
  3.   triangleAnimationLeft.fromValue = trianglePathSmall.CGPath 
  4.   triangleAnimationLeft.toValue = trianglePathLeftExtension.CGPath 
  5.   triangleAnimationLeft.beginTime = 0.0 
  6.   triangleAnimationLeft.duration = 0.3 
  7.   
  8.   var triangleAnimationRight: CABasicAnimation = CABasicAnimation(keyPath: "path"
  9.   triangleAnimationRight.fromValue = trianglePathLeftExtension.CGPath 
  10.   triangleAnimationRight.toValue = trianglePathRightExtension.CGPath 
  11.   triangleAnimationRight.beginTime = triangleAnimationLeft.beginTime + triangleAnimationLeft.duration 
  12.   triangleAnimationRight.duration = 0.25 
  13.   
  14.   var triangleAnimationTop: CABasicAnimation = CABasicAnimation(keyPath: "path"
  15.   triangleAnimationTop.fromValue = trianglePathRightExtension.CGPath 
  16.   triangleAnimationTop.toValue = trianglePathTopExtension.CGPath 
  17.   triangleAnimationTop.beginTime = triangleAnimationRight.beginTime + triangleAnimationRight.duration 
  18.   triangleAnimationTop.duration = 0.20 
  19.   
  20.   var triangleAnimationGroup: CAAnimationGroup = CAAnimationGroup() 
  21.   triangleAnimationGroup.animations = [triangleAnimationLeft, triangleAnimationRight,  
  22.                                       triangleAnimationTop] 
  23.   triangleAnimationGroup.duration = triangleAnimationTop.beginTime + triangleAnimationTop.duration 
  24.   triangleAnimationGroup.fillMode = kCAFillModeForwards 
  25.   triangleAnimationGroup.removedOnCompletion = false 
  26.   addAnimation(triangleAnimationGroup, forKey: nil) 

這段代碼使三角層TriangleLayer的角一個(gè)挨一個(gè)的被彈拉成為橢圓 OvalLayer 層的擺動(dòng)。Bezier path已經(jīng)作為啟動(dòng)工程的一部分被定義好。左邊的角首先執(zhí)行,接下來(lái)是右邊的角,最后是上面的。你完成這個(gè)(動(dòng)畫)需要借助創(chuàng)建三個(gè)基于路徑的CABasicAnimation類的實(shí)例, CABasicAnimation 類已經(jīng)被你添加到 CAAnimationGroup 組中,而組則被放到了 TriangleLayer 中。

構(gòu)建并運(yùn)行你的應(yīng)用,看看當(dāng)前動(dòng)畫的狀態(tài).

11.gif

完成變形

為了完成變形過(guò)程,你需要在縮小OvalLayer橢圓層的同時(shí),對(duì) HolderView 旋轉(zhuǎn)360度,讓 TriangleLayer 三角層單獨(dú)隔離出來(lái)。

打開 HolderView.swift,在 drawAnimatedTriangle(): 尾部添加如下代碼


  1. NSTimer.scheduledTimerWithTimeInterval(0.9, target: self, selector: "spinAndTransform"
  2.                           userInfo: nil, repeats: false

這里設(shè)置了一個(gè)定時(shí)器timer,用于在三角形動(dòng)畫結(jié)束后觸發(fā)。0.9s的時(shí)間還次用反復(fù)實(shí)驗(yàn)來(lái)確定

現(xiàn)在在這個(gè)類的底部添加如下的函數(shù)。


  1. func spinAndTransform() { 
  2.   // 1 
  3.   layer.anchorPoint = CGPointMake(0.50.6
  4.   
  5.   // 2 
  6.   var rotationAnimation: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z"
  7.   rotationAnimation.toValue = CGFloat(M_PI * 2.0
  8.   rotationAnimation.duration = 0.45 
  9.   rotationAnimation.removedOnCompletion = true 
  10.   layer.addAnimation(rotationAnimation, forKey: nil) 
  11.   
  12.   // 3 
  13.   ovalLayer.contract() 

你之前創(chuàng)建的定時(shí)器添加了這段代碼,定時(shí)器會(huì)在橢圓停止擺動(dòng)并且三角行的角出現(xiàn)的時(shí)候調(diào)用這個(gè)函數(shù)。在這里我們看下這個(gè)函數(shù)更詳細(xì)的(介紹)

  1. 更新層的錨點(diǎn)到略微靠近視圖中間的下方。這提供了一個(gè)看上去更加自然的旋轉(zhuǎn)。這是由于橢圓和三角形事實(shí)上比視圖中心在垂直方向上略微偏移。因此,如果視圖圍繞中心旋轉(zhuǎn),橢圓和三角形可能會(huì)垂直方向移動(dòng)

  2. 應(yīng)用一個(gè)CABasicAnimation類來(lái)對(duì)層做360度旋轉(zhuǎn),或者2*pi的弧度。旋轉(zhuǎn)是圍繞著Z軸,Z軸就是穿過(guò)屏幕,垂直于屏幕平面的軸

  3. 在OvalLayer中調(diào)用contract()來(lái)展示動(dòng)畫,這個(gè)動(dòng)畫會(huì)削減橢圓的尺寸直到消失

現(xiàn)在打開 OvalLayer.swift,添加如下代碼到 contract() 方法


  1. func contract() { 
  2.   var contractAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path"
  3.   contractAnimation.fromValue = ovalPathLarge.CGPath 
  4.   contractAnimation.toValue = ovalPathSmall.CGPath 
  5.   contractAnimation.duration = animationDuration 
  6.   contractAnimation.fillMode = kCAFillModeForwards 
  7.   contractAnimation.removedOnCompletion = false 
  8.   addAnimation(contractAnimation, forKey: nil) 

這段代碼應(yīng)用 CABasicAnimation 類,將 OvalLayer 設(shè)置它的初始路徑 ovalPathSmall。

構(gòu)建并運(yùn)行你的應(yīng)用程序,當(dāng)動(dòng)畫完成的時(shí)候,只有三角形應(yīng)該被留在屏幕上。

12.gif

繪制容器

在下面這部分,你將要繪畫一個(gè)矩形容器,用于創(chuàng)建一個(gè)閉合圈。你將會(huì)用到 RectangleLayer 的描邊屬性。你需要這樣做兩次,將紅色和藍(lán)色都作為描邊色。

打開 HolderView.swift, 像下面這樣聲明兩個(gè) RectangularLayer 常量,(位置)就在你稍早時(shí)候 triangleLayer 屬性的下面


  1. let redRectangleLayer = RectangleLayer()let blueRectangleLayer = RectangleLayer() 

接下來(lái)添加如下代碼到 spinAndTransform(): 的尾部。


  1. NSTimer.scheduledTimerWithTimeInterval(0.45, target: self,  
  2.                                        selector: "drawRedAnimatedRectangle",  
  3.                                        userInfo: nil, repeats: false
  4. NSTimer.scheduledTimerWithTimeInterval(0.65, target: self,  
  5.                                        selector: "drawBlueAnimatedRectangle",  
  6.                                        userInfo: nil, repeats: false

這里創(chuàng)建兩個(gè)定時(shí)器timer分別調(diào)用 drawRedAnimatedRectangle() 和 drawBlueAnimatedRectangle() 。旋轉(zhuǎn)動(dòng)畫結(jié)束后,首先需要畫出矩形,當(dāng)紅色矩形描邊繪畫接近完成的時(shí)候,藍(lán)色矩形描邊開始。

添加下面兩個(gè)方法頭此類的底部


  1. func drawRedAnimatedRectangle() { 
  2.   layer.addSublayer(redRectangleLayer) 
  3.   redRectangleLayer.animateStrokeWithColor(Colors.red) 
  4.   
  5. func drawBlueAnimatedRectangle() { 
  6.   layer.addSublayer(blueRectangleLayer) 
  7.   blueRectangleLayer.animateStrokeWithColor(Colors.blue) 

一旦你添加矩形層 RectangleLayer 作為 HolderView 的子層,你就要調(diào)用 animateStrokeWithColor(color:) 并通過(guò)適當(dāng)?shù)念伾珌?lái)繪畫出邊線。

現(xiàn)在打開 RectangleLayer.swift, 像下面這樣填充 animateStrokeWithColor(color:)


  1. func animateStrokeWithColor(color: UIColor) { 
  2.   strokeColor = color.CGColor 
  3.   var strokeAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd"
  4.   strokeAnimation.fromValue = 0.0 
  5.   strokeAnimation.toValue = 1.0 
  6.   strokeAnimation.duration = 0.4 
  7.   addAnimation(strokeAnimation, forKey: nil) 

這段代碼通過(guò)添加一個(gè) CABasicAnimation對(duì)象,在 RectangleLayer 矩形層周圍繪畫了一個(gè)描邊。CAShapeLayer 的 strokeEnd 的 key(也就是keyPath)指示了在路徑周圍多遠(yuǎn)的距離停止描邊。通過(guò)將這個(gè)屬性值從0調(diào)到1,你會(huì)產(chǎn)生一種路徑被從開始到結(jié)束都被繪畫的錯(cuò)覺(jué)。 而從1到0,將會(huì)產(chǎn)生整個(gè)路徑被抹去的錯(cuò)覺(jué)。

編譯并運(yùn)行你的應(yīng)用,查看兩個(gè)描邊是如何看起來(lái)像他們構(gòu)建的容器的。

13.gif

#p#

填充容器

動(dòng)畫的下一步就是填充容器。你要尋找到的效果就像是水填充到玻璃杯中。這是個(gè)非常棒的視覺(jué)特效,使之為一個(gè)大的飛濺特效

打開 HolderView.swift,在 RectangleLayer 屬性稍靠下添加如下的常量


  1. let arcLayer = ArcLayer() 

現(xiàn)在在drawBlueAnimatedRectangle():尾部添加如下的代碼


  1. NSTimer.scheduledTimerWithTimeInterval(0.40, target: self, selector: "drawArc",  
  2.                                        userInfo: nil, repeats: false

這(段代碼)創(chuàng)建了一個(gè)定時(shí)器,用于當(dāng)藍(lán)色 RectangleLayer 完成繪畫后調(diào)用 drawArc()

在類的結(jié)尾添加如下的函數(shù)


  1. func drawArc() { 
  2.   layer.addSublayer(arcLayer) 
  3.   arcLayer.animate() 

這段代碼是在你動(dòng)畫填充之前,添加了上面已經(jīng)創(chuàng)建ArcLayer 的實(shí)例對(duì)象到HolderView 層。

打開ArcLayer.swift 然后添加如下代碼到animate():


  1. func animate() { 
  2.   var arcAnimationPre: CABasicAnimation = CABasicAnimation(keyPath: "path"
  3.   arcAnimationPre.fromValue = arcPathPre.CGPath 
  4.   arcAnimationPre.toValue = arcPathStarting.CGPath 
  5.   arcAnimationPre.beginTime = 0.0 
  6.   arcAnimationPre.duration = animationDuration 
  7.   
  8.   var arcAnimationLow: CABasicAnimation = CABasicAnimation(keyPath: "path"
  9.   arcAnimationLow.fromValue = arcPathStarting.CGPath 
  10.   arcAnimationLow.toValue = arcPathLow.CGPath 
  11.   arcAnimationLow.beginTime = arcAnimationPre.beginTime + arcAnimationPre.duration 
  12.   arcAnimationLow.duration = animationDuration 
  13.   
  14.   var arcAnimationMid: CABasicAnimation = CABasicAnimation(keyPath: "path"
  15.   arcAnimationMid.fromValue = arcPathLow.CGPath 
  16.   arcAnimationMid.toValue = arcPathMid.CGPath 
  17.   arcAnimationMid.beginTime = arcAnimationLow.beginTime + arcAnimationLow.duration 
  18.   arcAnimationMid.duration = animationDuration 
  19.   
  20.   var arcAnimationHigh: CABasicAnimation = CABasicAnimation(keyPath: "path"
  21.   arcAnimationHigh.fromValue = arcPathMid.CGPath 
  22.   arcAnimationHigh.toValue = arcPathHigh.CGPath 
  23.   arcAnimationHigh.beginTime = arcAnimationMid.beginTime + arcAnimationMid.duration 
  24.   arcAnimationHigh.duration = animationDuration 
  25.   
  26.   var arcAnimationComplete: CABasicAnimation = CABasicAnimation(keyPath: "path"
  27.   arcAnimationComplete.fromValue = arcPathHigh.CGPath 
  28.   arcAnimationComplete.toValue = arcPathComplete.CGPath 
  29.   arcAnimationComplete.beginTime = arcAnimationHigh.beginTime + arcAnimationHigh.duration 
  30.   arcAnimationComplete.duration = animationDuration 
  31.   
  32.   var arcAnimationGroup: CAAnimationGroup = CAAnimationGroup() 
  33.   arcAnimationGroup.animations = [arcAnimationPre, arcAnimationLow, arcAnimationMid,  
  34.                                   arcAnimationHigh, arcAnimationComplete] 
  35.   arcAnimationGroup.duration = arcAnimationComplete.beginTime + arcAnimationComplete.duration 
  36.   arcAnimationGroup.fillMode = kCAFillModeForwards 
  37.   arcAnimationGroup.removedOnCompletion = false 
  38.   addAnimation(arcAnimationGroup, forKey: nil) 

這個(gè)動(dòng)畫和之前的搖擺動(dòng)畫很相似。你創(chuàng)建了一個(gè) CAAnimationGroup 動(dòng)畫組,動(dòng)畫組中包含五個(gè)基于路徑的 CABasicAnimation 實(shí)例對(duì)象。

每個(gè)路徑因高度遞增而有了稍微不同的弧,這些路徑也是啟動(dòng)項(xiàng)目的一部分。最后,將 CAAnimationGroup 動(dòng)畫組應(yīng)用到層中,并使得動(dòng)畫組在完成的時(shí)候不會(huì)被移除,因而當(dāng)動(dòng)畫完成的時(shí)候,它依然保留了自己的狀態(tài)。

構(gòu)建并運(yùn)行你的應(yīng)用,看看這個(gè)神奇的展開吧。

14.gif

完成動(dòng)畫

剩下要做的就是擴(kuò)展藍(lán)色的HolderView視圖來(lái)填充整個(gè)屏幕,并且添加一個(gè)UILabel作為一個(gè)logo添加到視圖中

打開 HolderView.swift,在drawArc() 的結(jié)尾添加如下代碼


  1. NSTimer.scheduledTimerWithTimeInterval(0.90, target: self, selector: "expandView",  
  2.                                        userInfo: nil, repeats: false

這(段代碼)創(chuàng)建了一個(gè)定時(shí)器,用于在 ArcLayer 填充到容器后調(diào)用 expandView()

現(xiàn)在,添加下面的函數(shù)到同一個(gè)類的底部:


  1. func expandView() { 
  2.   // 1 
  3.   backgroundColor = Colors.blue 
  4.   
  5.   // 2 
  6.   frame = CGRectMake(frame.origin.x - blueRectangleLayer.lineWidth,  
  7.                      frame.origin.y - blueRectangleLayer.lineWidth,  
  8.                      frame.size.width + blueRectangleLayer.lineWidth * 2,  
  9.                      frame.size.height + blueRectangleLayer.lineWidth * 2
  10.   
  11.   // 3 
  12.   layer.sublayers = nil 
  13.   
  14.   // 4 
  15.   UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, 
  16.     animations: { 
  17.       self.frame = self.parentFrame 
  18.     }, completion: { finished in 
  19.       self.addLabel() 
  20.     }) 

代碼分析

  1. HolderView視圖的背景設(shè)置為藍(lán)色,和你填充到矩形的顏色匹配

  2. 幀擴(kuò)展到你稍早時(shí)候添加的RectangleLayer矩形層的描邊寬度,

  3. 所有的子層都移除。現(xiàn)在沒(méi)有了橢圓,沒(méi)有了三角形,沒(méi)有了矩形圖層

  4. 添加動(dòng)畫,并擴(kuò)張HolderView填充屏幕,當(dāng)動(dòng)畫結(jié)束的時(shí)候,調(diào)用addLabel().

在類的底部,添加如下函數(shù)


  1. func addLabel() { 
  2.   delegate?.animateLabel() 

這里只是簡(jiǎn)單的調(diào)用視圖的代理函數(shù),展示label標(biāo)簽。

現(xiàn)在打開ViewController.swift,添加如下代碼到animateLabel():


  1. func animateLabel() { 
  2.   // 1 
  3.   holderView.removeFromSuperview() 
  4.   view.backgroundColor = Colors.blue 
  5.   
  6.   // 2   
  7.   var label: UILabel = UILabel(frame: view.frame) 
  8.   label.textColor = Colors.white 
  9.   label.font = UIFont(name: "HelveticaNeue-Thin", size: 170.0
  10.   label.textAlignment = NSTextAlignment.Center 
  11.   label.text = "S" 
  12.   label.transform = CGAffineTransformScale(label.transform, 0.250.25
  13.   view.addSubview(label) 
  14.   
  15.   // 3   
  16.   UIView.animateWithDuration(0.4, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.1, options: UIViewAnimationOptions.CurveEaseInOut, 
  17.     animations: ({ 
  18.       label.transform = CGAffineTransformScale(label.transform, 4.04.0
  19.     }), completion: { finished in 
  20.       self.addButton() 
  21.     }) 

依次帶入各個(gè)注釋段

  1. 從視圖中移除HolderView ,并設(shè)置視圖的背景顏色為藍(lán)色。

  2. 創(chuàng)建一個(gè)文本為"S"的UIlabel標(biāo)簽對(duì)象,用于展示logo,并添加到視圖。

  3. 標(biāo)簽對(duì)象使用一個(gè)彈性動(dòng)畫來(lái)使之伸縮。一旦動(dòng)畫結(jié)束,調(diào)用 addButton() 來(lái)添加一個(gè)按鈕到視圖中,當(dāng)按鈕按下的時(shí)候,重復(fù)動(dòng)畫。

構(gòu)建并運(yùn)行應(yīng)用程序,給自己點(diǎn)個(gè)贊,花個(gè)時(shí)間來(lái)欣賞自己構(gòu)建的動(dòng)畫吧。

15.gif

下一步

你可以從這里 下載 最終完整的項(xiàng)目。

這個(gè)指導(dǎo)書包含了相當(dāng)多的不一樣的動(dòng)畫技術(shù),當(dāng)這些動(dòng)畫都堆疊在一起的時(shí)候,能夠創(chuàng)造一個(gè)相當(dāng)復(fù)雜的加載動(dòng)畫,這確實(shí)能夠讓你的應(yīng)用在第一次被(用戶)運(yùn)行的時(shí)候就眼前一亮。

從這里,放松自由的玩玩不一樣的(動(dòng)畫 的)定時(shí)和形狀,看看你能組裝成哪些很酷的動(dòng)畫

如果你想讓你新發(fā)現(xiàn)的動(dòng)畫技術(shù)提升一個(gè)檔次,那我建議你看下我們的(這本)書iOS Animations by Tutorials.

我希望通過(guò)這本指導(dǎo)書你能得到極大的樂(lè)趣,并且,如果你有任何問(wèn)題或者建議,請(qǐng)加入我們下面的論壇討論吧

責(zé)任編輯:倪明 來(lái)源: CocoaChina
相關(guān)推薦

2009-09-18 11:44:05

Scala實(shí)例教程Kestrel

2014-08-26 11:46:46

QtAndroid實(shí)例教程

2019-06-17 15:25:17

expandunexpandLinux

2010-08-17 11:02:45

DIV CSS實(shí)例教程

2011-07-25 16:03:47

XCode 編譯

2009-09-08 14:18:35

NFS服務(wù)器

2013-01-04 16:17:33

Android開發(fā)圖像特效圖像處理

2025-01-20 00:00:00

反射Java語(yǔ)言

2013-01-14 17:05:55

UCUI設(shè)計(jì)菜單欄

2009-07-30 14:18:02

ASP.NET實(shí)例教程

2010-08-25 17:08:18

實(shí)例教程

2025-04-01 08:00:00

curl開發(fā)運(yùn)維

2018-09-29 15:34:34

JavaList接口

2021-05-21 12:36:16

限流代碼Java

2024-03-06 08:15:03

@Autowired注入方式Spring

2020-06-04 14:15:55

Java中BigDecimal函數(shù)

2013-07-25 14:44:48

sqlite實(shí)例教程iOS開發(fā)學(xué)習(xí)sqlite打造詞典

2013-08-15 09:14:55

2010-06-18 15:55:47

UML建模

2009-10-23 16:27:10

VB.NET實(shí)例教程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)