如何用Swift創建一個復雜的加載動畫

現在在蘋果應用商店上有超過140萬的App,想讓你的app事件非常具有挑戰的事情。你有這樣一個機會,在你的應用的數據完全加載出來之前,你可以通過一個很小的窗口來捕獲用戶的關注。

沒有比這個更好的地方讓用戶大為贊嘆,當你的應用程序載入畫面的時候,你可以添加一個愉快的動畫,作為先導,以加載你的應用。

在本教程中,你將學習如何做出這樣的動畫。你將學習如何建立piece-by-piece,采用前衛的技術來創建一個流體和迷人的動畫。

準備

下載本教程開始的工程,把它保存到一個方便的地方,并在Xcode中打開。

打開HolderView.swift。在這個UIView的子類中,添加下面的子層在動畫的上面展示:

OvalLayer.swift:這是第一層,從0慢慢變大,然后很短的時間抖動

TriangleLayer.swift:OvalLayer層正在抖動的時候出現,當這層旋轉的時候,OvalLayer收縮到沒有,只讓TriangleLayer可視

RectangleLayer.swift:這層作為TriangleLayer可視的容器

ArcLayer.swift:這層填充RectangleLayer通過一個動畫,類似于玻璃中充滿水的樣子

打開OvalLayer.swift,最初的項目已經包含了初始化這些層和所有在你的動畫中將使用的貝塞爾路徑的代碼。你會看到expand(),wobble()contract()這些方法里面都是空的,通過這個教程你將填充這些方法。所有其他的*Layer的文件都是類似的功能結構。

Note:如果你想學習關于貝塞爾路徑的知識,可以點擊這個教程Modern Core Graphics with Swift

最后,打開ViewController.swift,看到addHolderView(),這個方法中添加了HolderView的實例對象,作為控制器視圖的中心的子視圖。這個視圖將包含所有的動畫。該視圖控制器只需要將它放在屏幕上,然后該視圖將執行實際的動畫的代碼。

animateLabel()方法是有HolderView類提供的代理回調,當你完成動畫的次序時,你將會填充它。

addButton()僅僅是在視圖上增加了一個按鈕,以便您可以點擊并重新啟動動畫。

構建并運行該項目,你應該看到一個空白的屏幕。這是件完美的事情在空白的畫布上開始制作你新的動畫!

在教程的最后,你的app將會是下面這樣的:

因此,事不宜遲,讓我們開始吧!

添加橢圓

動畫開始有個紅色的橢圓形,然后擴展到視圖的中心,然后微微搖晃。

打開HolderView.swift,然后在HolderView上方附近定義下面的常量:

let?ovalLayer?=?OvalLayer()

添加下面的方法:

func?addOval()?{

layer.addSublayer(ovalLayer)

ovalLayer.expand()

}

你第一次添加的OvalLayer的實例作為視圖層的子視圖。

OvalLayer.swift中,添加下面的代碼到expand()中:

func?expand()?{

var?expandAnimation:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

expandAnimation.fromValue?=?ovalPathSmall.CGPath

expandAnimation.toValue?=?ovalPathLarge.CGPath

expandAnimation.duration?=?animationDuration

expandAnimation.fillMode?=?kCAFillModeForwards

expandAnimation.removedOnCompletion?=?false

addAnimation(expandAnimation,?forKey:?nil)

}

這個方法創建了一個CABasicAnimation實例,來改變橢圓的路徑從ovalPathSmallovalPathLarge。初始的項目中為你提供了這些貝塞爾路徑。設置removedOnCompletionfalsefillMode的值為KCAFillModeForwards,在動畫中一旦動畫完成,讓橢圓開辟一個新的路徑。

最后,打開ViewController.swift,添加下面那一行到addHolderView(),就在view.addSubview(holderView)的下面:

holderView.addOval()

addOval在橢圓被添加到控制器的視圖中后開始動畫。

構建并運行你的app,你的動畫將會顯示下面這樣:

晃動橢圓

在橢圓被添加到視圖中并擴展后,下一步就是在步驟中加一些反彈,讓其擺動。

打開HolderView.swift,然后添加下面的方法:

func?wobbleOval()?{

ovalLayer.wobble()

}

這個方法是讓其在OvalLayer中擺動。

打開OvalLayer.swift,在wobble()中添加下面的代碼:

func?wobble()?{

//?1

var?wobbleAnimation1:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

wobbleAnimation1.fromValue?=?ovalPathLarge.CGPath

wobbleAnimation1.toValue?=?ovalPathSquishVertical.CGPath

wobbleAnimation1.beginTime?=?0.0

wobbleAnimation1.duration?=?animationDuration

//?2

var?wobbleAnimation2:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

wobbleAnimation2.fromValue?=?ovalPathSquishVertical.CGPath

wobbleAnimation2.toValue?=?ovalPathSquishHorizontal.CGPath

wobbleAnimation2.beginTime?=?wobbleAnimation1.beginTime?+?wobbleAnimation1.duration

wobbleAnimation2.duration?=?animationDuration

//?3

var?wobbleAnimation3:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

wobbleAnimation3.fromValue?=?ovalPathSquishHorizontal.CGPath

wobbleAnimation3.toValue?=?ovalPathSquishVertical.CGPath

wobbleAnimation3.beginTime?=?wobbleAnimation2.beginTime?+?wobbleAnimation2.duration

wobbleAnimation3.duration?=?animationDuration

//?4

var?wobbleAnimation4:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

wobbleAnimation4.fromValue?=?ovalPathSquishVertical.CGPath

wobbleAnimation4.toValue?=?ovalPathLarge.CGPath

wobbleAnimation4.beginTime?=?wobbleAnimation3.beginTime?+?wobbleAnimation3.duration

wobbleAnimation4.duration?=?animationDuration

//?5

var?wobbleAnimationGroup:?CAAnimationGroup?=?CAAnimationGroup()

wobbleAnimationGroup.animations?=?[wobbleAnimation1,?wobbleAnimation2,?wobbleAnimation3,

wobbleAnimation4]

wobbleAnimationGroup.duration?=?wobbleAnimation4.beginTime?+?wobbleAnimation4.duration

wobbleAnimationGroup.repeatCount?=?2

addAnimation(wobbleAnimationGroup,?forKey:?nil)

}

這里有很多的代碼,但它分解的很好,來看下這里干了些什么:

1、從遠處到垂直壓扁

2、從垂直壓扁改為水平和垂直都壓扁

3、切換回垂直壓扁

4、完成動畫,結束回到最開始的位置

5、將所有的動畫整合到CAAnimationGroup中,然后將這組動畫添加到OvalLayout中。

每個后續動畫的beginTime是先前動畫的beginTime和其持續時間的總和。重復這個動畫組兩次,就會看到搬動稍微拉長。

即時你現在添加了所有搖晃動畫的代碼,你也看不到你想看到的動畫。

回到HolderView.swift中,添加下面的代碼到addOval()中:

NSTimer.scheduledTimerWithTimeInterval(0.3,?target:?self,?selector:?"wobbleOval",

userInfo:?nil,?repeats:?false)

這里創建了一個定時器,在OvalLayer完成擴展動畫后,調用wobbleOval()

構建并運行你的app,看下現在的動畫:

這是非常微妙的,但這是一個非常重要的因素去創建一個真正令人愉快的動畫。你不需要讓其充滿整個屏幕!

開始變形

即將看到神奇的事情!你即將把橢圓變成三角形。在用戶的眼中,這個轉變應該看上去是完全無縫的。那么你需要使用兩個顏色相同的單獨的形狀來實現它。

打開HolderView.swift,添加下面的代碼到HolderView中,就在你之前添加的ovalLayer常量的下面:

let?triangleLayer?=?TriangleLayer()

這里定義了一個TriangleLayer實例,跟你之前定義的ovalLayer一樣。

現在,實現wobbleOval()方法:

func?wobbleOval()?{

//?1

layer.addSublayer(triangleLayer)?//?Add?this?line

ovalLayer.wobble()

//?2

//?Add?the?code?below

NSTimer.scheduledTimerWithTimeInterval(0.9,?target:?self,

selector:?"drawAnimatedTriangle",?userInfo:?nil,

repeats:?false)

}

這段代碼做了下面這些事情:

1、該行添加了前面初始化的TriangleLayer實例,作為HolderView層里的一個子層

2、之前知道了擺動動畫運行兩次的總共時間是1.8,中間的地方將會是一個非常好的地方去開始變形處理。因此,添加一個計時器,在延遲0.9后,執行drawAnimatedTriangle()方法。

Note:在動畫中尋找中一個正確的持續時間或者延遲時間需要一些實驗和錯誤的嘗試,然后才能發現一個好的動畫和完美的動畫的區別。我鼓勵你去和你的動畫去鼓搗,讓它們變得更完美。這可能需要一些時間,但它是值得的。

接下來,添加下面的功能:

func?drawAnimatedTriangle()?{

triangleLayer.animate()

}

這個方法是實現剛剛寫的定時器的功能,它讓三角形開始動。

現在,打開TriangleLayer.swift,然后添加下面的代碼到animate()中:

func?animate()?{

var?triangleAnimationLeft:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

triangleAnimationLeft.fromValue?=?trianglePathSmall.CGPath

triangleAnimationLeft.toValue?=?trianglePathLeftExtension.CGPath

triangleAnimationLeft.beginTime?=?0.0

triangleAnimationLeft.duration?=?0.3

var?triangleAnimationRight:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

triangleAnimationRight.fromValue?=?trianglePathLeftExtension.CGPath

triangleAnimationRight.toValue?=?trianglePathRightExtension.CGPath

triangleAnimationRight.beginTime?=?triangleAnimationLeft.beginTime?+?triangleAnimationLeft.duration

triangleAnimationRight.duration?=?0.25

var?triangleAnimationTop:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

triangleAnimationTop.fromValue?=?trianglePathRightExtension.CGPath

triangleAnimationTop.toValue?=?trianglePathTopExtension.CGPath

triangleAnimationTop.beginTime?=?triangleAnimationRight.beginTime?+?triangleAnimationRight.duration

triangleAnimationTop.duration?=?0.20

var?triangleAnimationGroup:?CAAnimationGroup?=?CAAnimationGroup()

triangleAnimationGroup.animations?=?[triangleAnimationLeft,?triangleAnimationRight,

triangleAnimationTop]

triangleAnimationGroup.duration?=?triangleAnimationTop.beginTime?+?triangleAnimationTop.duration

triangleAnimationGroup.fillMode?=?kCAFillModeForwards

triangleAnimationGroup.removedOnCompletion?=?false

addAnimation(triangleAnimationGroup,?forKey:?nil)

}

這段代碼讓三角形的角伴隨著OvalLayer層的晃動一個一個出來;在最初的項目中貝塞爾路徑已經定義了每個角。最左邊的角第一個出來,接著是右邊的,最后是最上面的那個角。通過創建三個基于CABasicAnimation的實例,添加到CAAnimationGroup中。

構建并運行你的app,將會看到目前的動畫狀態;當橢圓晃動的時候,三角形的每個角開始出來知道三個角全部顯示出來,就像這樣:

完成變形

要實現其變形,你需要讓HolderView360度旋轉當OvalLayer收縮的時候,最終僅留下TriangleLayer

打開HolderView.swift,添加下面的代碼在drawAnimatedTriangle()的最后:

NSTimer.scheduledTimerWithTimeInterval(0.9,?target:?self,?selector:?"spinAndTransform",

userInfo:?nil,?repeats:?false)

在三角形動畫完成后設置一個定時器,0.9秒的這個時間也是一次次通過嘗試而得到的。

現在,添加下面的方法:

func?spinAndTransform()?{

//?1

layer.anchorPoint?=?CGPointMake(0.5,?0.6)

//?2

var?rotationAnimation:?CABasicAnimation?=?CABasicAnimation(keyPath:?"transform.rotation.z")

rotationAnimation.toValue?=?CGFloat(M_PI?*?2.0)

rotationAnimation.duration?=?0.45

rotationAnimation.removedOnCompletion?=?true

layer.addAnimation(rotationAnimation,?forKey:?nil)

//?3

ovalLayer.contract()

}

剛剛創建的定時器一旦橢圓晃動停止并且三角形的每個角都出現時調用這個函數。下面看下這個函數的詳細功能:

1、更新該層的錨點略低于視圖的中心。這讓旋轉閑的更加自然。這是因為,橢圓和三角形事實上以垂直方向從視圖的中心偏離。因此,如果視圖繞著中心旋轉,那么橢圓和三角似乎是垂直移動的。

2、CABasicAnimation讓圖層旋轉360度或者2π弧度。旋轉是繞著z軸,垂直于屏幕的表面進入和移出。

3、OvalLayer調用contract()方法執行動畫,縮減橢圓的大小直至看不見。

現在,打開OvalLayer.swift,然后添加下面的代碼到contract()中:

func?contract()?{

var?contractAnimation:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

contractAnimation.fromValue?=?ovalPathLarge.CGPath

contractAnimation.toValue?=?ovalPathSmall.CGPath

contractAnimation.duration?=?animationDuration

contractAnimation.fillMode?=?kCAFillModeForwards

contractAnimation.removedOnCompletion?=?false

addAnimation(contractAnimation,?forKey:?nil)

}

這是讓OvalLayer返回最開始的路徑上ovalPathSmall,通過執行一個CABasicAnimation動畫。這是跟之前調用的動畫是相反的。

構建并運行你的app;一旦動畫結束后,就只剩下三角形在屏幕的中間。

繪制容器

在接下來的部分中,你將會繪制一個長方形的容器來創建一個外殼。要做到這一點,你需要使用RectangleLayer的畫筆。你將要做兩次,通過使用紅色和藍色作為筆的顏色。

打開HolderView.swift,然后定義兩個RectangularLayer常量,如下,在triangleLayer的下方:

let?redRectangleLayer?=?RectangleLayer()

let?blueRectangleLayer?=?RectangleLayer()

接下來添加下面的代碼在spinAndTransform()的后面:

NSTimer.scheduledTimerWithTimeInterval(0.45,?target:?self,

selector:?"drawRedAnimatedRectangle",

userInfo:?nil,?repeats:?false)

NSTimer.scheduledTimerWithTimeInterval(0.65,?target:?self,

selector:?"drawBlueAnimatedRectangle",

userInfo:?nil,?repeats:?false)

這里你創建了兩個定時器分別調用drawRedAnimatedRectangle()drawBlueAnimatedRectangle()

首先畫紅色的矩形框,之后完成向右的一個旋轉動畫。在紅色的矩形框繪制接近完成的時候開始繪制藍色的矩形框。

添加下面的兩個方法:

func?drawRedAnimatedRectangle()?{

layer.addSublayer(redRectangleLayer)

redRectangleLayer.animateStrokeWithColor(Colors.red)

}

func?drawBlueAnimatedRectangle()?{

layer.addSublayer(blueRectangleLayer)

blueRectangleLayer.animateStrokeWithColor(Colors.blue)

}

一旦你添加RectangleLayer作為HolderView的一個子層時,就開始調用animateStrokeWithColor(color:),并開始執行繪制邊框的動畫。

現在打開RectangleLayer.swift,填充animateStrokeWithColor(color:)方法,如下:

func?animateStrokeWithColor(color:?UIColor)?{

strokeColor?=?color.CGColor

var?strokeAnimation:?CABasicAnimation?=?CABasicAnimation(keyPath:?"strokeEnd")

strokeAnimation.fromValue?=?0.0

strokeAnimation.toValue?=?1.0

strokeAnimation.duration?=?0.4

addAnimation(strokeAnimation,?forKey:?nil)

}

這里通過添加一個CABasicAnimation去繪制一個筆。CAShapeLayer中的strokeEnd指示著畫筆去描繪這個矩形框。

構建并運行你的app,將會看到下面的動畫:

填充容器

現在有了容器,下一步就是將它填補起來。這個效果類似于水填充滿玻璃,這是一個偉大的詩視覺效果!

打開HolderView.swift,就在RectangleLayer屬性的后面,添加一個常量:

let?arcLayer?=?ArcLayer()

添加下面的代碼在drawBlueAnimatedRectangle()的最后面:

NSTimer.scheduledTimerWithTimeInterval(0.40,?target:?self,?selector:?"drawArc",

userInfo:?nil,?repeats:?false)

這里創建了一個計時器,一旦藍色的RectangleLayer繪制完成后便去調用drawArc()

添加下面的方法:

func?drawArc()?{

layer.addSublayer(arcLayer)

arcLayer.animate()

}

在執行動畫之前,這里增加了一個在HolderView層上已經創建了的ArcLayer的實例。

打開ArcLayer.swift,添加下面的代碼到animate()方法中:

func?animate()?{

var?arcAnimationPre:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

arcAnimationPre.fromValue?=?arcPathPre.CGPath

arcAnimationPre.toValue?=?arcPathStarting.CGPath

arcAnimationPre.beginTime?=?0.0

arcAnimationPre.duration?=?animationDuration

var?arcAnimationLow:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

arcAnimationLow.fromValue?=?arcPathStarting.CGPath

arcAnimationLow.toValue?=?arcPathLow.CGPath

arcAnimationLow.beginTime?=?arcAnimationPre.beginTime?+?arcAnimationPre.duration

arcAnimationLow.duration?=?animationDuration

var?arcAnimationMid:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

arcAnimationMid.fromValue?=?arcPathLow.CGPath

arcAnimationMid.toValue?=?arcPathMid.CGPath

arcAnimationMid.beginTime?=?arcAnimationLow.beginTime?+?arcAnimationLow.duration

arcAnimationMid.duration?=?animationDuration

var?arcAnimationHigh:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

arcAnimationHigh.fromValue?=?arcPathMid.CGPath

arcAnimationHigh.toValue?=?arcPathHigh.CGPath

arcAnimationHigh.beginTime?=?arcAnimationMid.beginTime?+?arcAnimationMid.duration

arcAnimationHigh.duration?=?animationDuration

var?arcAnimationComplete:?CABasicAnimation?=?CABasicAnimation(keyPath:?"path")

arcAnimationComplete.fromValue?=?arcPathHigh.CGPath

arcAnimationComplete.toValue?=?arcPathComplete.CGPath

arcAnimationComplete.beginTime?=?arcAnimationHigh.beginTime?+?arcAnimationHigh.duration

arcAnimationComplete.duration?=?animationDuration

var?arcAnimationGroup:?CAAnimationGroup?=?CAAnimationGroup()

arcAnimationGroup.animations?=?[arcAnimationPre,?arcAnimationLow,?arcAnimationMid,

arcAnimationHigh,?arcAnimationComplete]

arcAnimationGroup.duration?=?arcAnimationComplete.beginTime?+?arcAnimationComplete.duration

arcAnimationGroup.fillMode?=?kCAFillModeForwards

arcAnimationGroup.removedOnCompletion?=?false

addAnimation(arcAnimationGroup,?forKey:?nil)

}

這個動畫非常類似于之前的擺動的動畫;創建了一個CAAnimationGroup,包含5個基于路徑的CABasicAnimation實例。每個路徑隨著高度的增加都有一個稍微不同的弧度。最后,將CAAnimationGroup應用到圖層中,并指示著它不被移除,在動畫完成之前將保持這個狀態。

構建并運行你的app,將會看到神奇的一幕!

完成動畫

剩下的事情就是將藍色的HolderView擴大直至填充滿整個屏幕,并在視圖添加一個UILabel作為logo。

打開HolderView.swift,添加下面的代碼到drawArc()的最后面:

NSTimer.scheduledTimerWithTimeInterval(0.90,?target:?self,?selector:?"expandView",

userInfo:?nil,?repeats:?false)

這里創建了一個計時器,當ArcLayer填充滿容器的時候調用expandView()

現在,添加下面的方法:

func?expandView()?{

//?1

backgroundColor?=?Colors.blue

//?2

frame?=?CGRectMake(frame.origin.x?-?blueRectangleLayer.lineWidth,

frame.origin.y?-?blueRectangleLayer.lineWidth,

frame.size.width?+?blueRectangleLayer.lineWidth?*?2,

frame.size.height?+?blueRectangleLayer.lineWidth?*?2)

//?3

layer.sublayers?=?nil

//?4

UIView.animateWithDuration(0.3,?delay:?0.0,?options:?UIViewAnimationOptions.CurveEaseInOut,

animations:?{

self.frame?=?self.parentFrame

},?completion:?{?finished?in

self.addLabel()

})

}

該方法做了寫什么事情呢:

1、holder view的背景被設置為藍色,和你之前填充的矩形框的顏色一樣;

2、這個frame擴大到之前設定的RectangleLayer畫筆的寬度;

3、所有的子層都被移除。現在沒有橢圓,沒有三角形,沒有矩形圖層;

4、添加一個動畫,讓HolderView擴大至填充滿整個屏幕。一旦該動畫執行了,你需要調用addLabel()方法;

在下面添加該方法:

func?addLabel()?{

delegate?.animateLabel()

}

動畫顯示這個Label僅僅使用了視圖的委托動能。

現在打開ViewController.swift,添加下面的代碼到animateLabel()中:

func?animateLabel()?{

//?1

holderView.removeFromSuperview()

view.backgroundColor?=?Colors.blue

//?2

var?label:?UILabel?=?UILabel(frame:?view.frame)

label.textColor?=?Colors.white

label.font?=?UIFont(name:?"HelveticaNeue-Thin",?size:?170.0)

label.textAlignment?=?NSTextAlignment.Center

label.text?=?"S"

label.transform?=?CGAffineTransformScale(label.transform,?0.25,?0.25)

view.addSubview(label)

//?3

UIView.animateWithDuration(0.4,?delay:?0.0,?usingSpringWithDamping:?0.7,?initialSpringVelocity:?0.1,?options:?UIViewAnimationOptions.CurveEaseInOut,

animations:?({

label.transform?=?CGAffineTransformScale(label.transform,?4.0,?4.0)

}),?completion:?{?finished?in

self.addButton()

})

}

依次注釋每個部分:

1、將HolderView從視圖上移除,并設置視圖的背景顏色為藍色;

2、創建UILabel,內容為“S”,作為logo,添加到視圖中;

3、執行一個彈簧動畫顯示那個Label。一旦動畫執行完,調用addButton()方法,在視圖中添加一個按鈕,當點擊時,重復顯示該動畫過程。

構建并運行你的app,給自己鼓掌吧,然后花點時間來享受自己實現了什么!

你可以到這里下載完整的項目

由于第一次翻譯外文,可能很多缺陷和不足,求各路大神指正!無比感謝!原文地址

此譯文已發表在我的CSDN博客上zmp1123

另外,獲取更多的iOS開發的相關資料、資訊、課程,可關注iOS開發者開發者公眾平臺!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,537評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,130評論 5 13
  • 在iOS實際開發中常用的動畫無非是以下四種:UIView動畫,核心動畫,幀動畫,自定義轉場動畫。 1.UIView...
    請叫我周小帥閱讀 3,128評論 1 23
  • Core Animation Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,...
    45b645c5912e閱讀 3,044評論 0 21
  • iOS動畫篇之CoreAnimation動畫 9月 22, 2016發布在Objective-C App如果想被大...
    白水灬煮一切閱讀 2,060評論 0 0