輪盤猜大?。ǚ绿詫毑势盇pp)

支持原創(chuàng),原文地址:www.KentonYu.com

作品集,其實也談不上作品吧。都是一些小 Demo 。我覺得有必要把一些覺得有意思的東西放在這里展示一下。讓大家來吐槽一下。并不斷的改進(jìn)。但是有一個傷透腦經(jīng)的問題,App 開發(fā)并不好展示,特別是 iOS,當(dāng)然有值得展示的上架應(yīng)用就會把 App Store link 放上來,那些小 Demo ,就只能先上錄屏了。

錄屏播放地址

主要知識點


貝塞爾曲線

給定n+1個數(shù)據(jù)點,p0(x0 , y0) ... pn(xn , yn),生成一條曲線,使得該曲線與這些點所連結(jié)的折線相近。在數(shù)學(xué)中,這屬于逼近問題。在幾何中,可以形象地理解為先用折線段連接這些數(shù)據(jù)點,勾勒出圖形的大致輪廓,然后再用光滑的曲線去盡可能接近地擬合這條折線。摘錄來自: “A GUIDE TO IOS ANIMATION”

UIBezierPath,是 UIKit 對 CoreGraphics 的 path (CGPathRef)的封裝。通過 UIBezierPath 可以繪制直線、圓圈、多邊形和貝塞爾曲線。
下面是對 UIBezierPath 的簡單介紹

<pre>
// 以下是四個類方法,用來繪制閉合的特殊路徑
// 矩形

  • (UIBezierPath *)bezierPathWithRect:(CGRect)rect

// 圓角矩形

  • (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius

// 矩形內(nèi)切圓

  • (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect

// 弧形(clockwise 是否順時針繪制)

  • (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
    </pre>
    <pre>
    // 實例方法,可以繪制各種自定義的形狀
    // 直線
  • (void)addLineToPoint:(CGPoint)point

// 弧形線段

  • (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise

// 二階貝塞爾曲線

  • (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

// 三階貝塞爾曲線

  • (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
    </pre>

通過貝塞爾曲線可以繪制任何你想要畫的形狀。我還沒用過三階貝塞爾。這個<a target="_blank" style='color:#00d6cf'>網(wǎng)站</a>可以體驗下貝塞爾曲線。


CALayer

CALayer 類在概念上和 UIView 類似,同樣也是一些被層級關(guān)系樹管理的矩形塊,同樣也可以包含一些內(nèi)容(圖片,文本或者背景色),管理子圖層的位置。它們有一些方法和屬性用來做動畫和變換。和 UIView 最大的不同是 CALayer 不處理用戶的交互( UIView 繼承 UIResponder,CALayer 繼承 NSObject )。


CALayer 和 UIView 主要區(qū)別:

  • 處理觸摸事件
  • 陰影、圓角、帶顏色的邊框
  • 3D 變換
  • 非矩形范圍
  • 透明遮罩
  • 多級非線性動畫
  • .....


CALayer 的子類簡單介紹:

  • CAShapeLayer:用來繪制各種形狀
  • CATextLayer:用來繪制文字
  • CATransformLayer:用來構(gòu)造一個層級的3D結(jié)構(gòu)
  • CAGradientLayer:用來生成兩種或更多顏色平滑漸變
  • CAReplicatorLayer:用來高效地生成許多相似的圖層
  • CAScrollLayer:用來實現(xiàn)圖層滑動
  • CATiledLayer:為載入大圖造成的性能問題提供一個解決方案,將大圖分解成小片然后將它們單獨(dú)按需載入
  • CAEmitterLayer:高性能的粒子引擎,被用來創(chuàng)建實時粒子動畫(煙、火、雨等)
  • CAEAGLLayer:The CAEAGLLayer class supports drawing OpenGL content in iPhone applications
  • AVPlayerLayer:用來在iOS上播放視頻的,是 MPMoivePlayer 的底層實現(xiàn),由 AVFoundation 提供

<b>關(guān)于這一部分的具體實踐,后續(xù)會補(bǔ)上。</b>


我們什么時候需要使用 CALayer:

  • 開發(fā)同時可以運(yùn)行在 MAC OS 上的跨平臺應(yīng)用
  • 使用多種 CALayer 的子類
  • 做一些對性能要求很高的工作


drawRect && drawLayer

CALayer 有一個寄宿圖,可以通過 contents 屬性來賦值:
<pre>
layer.contents = (__bridge id)image.CGImage;
</pre>

當(dāng)用代碼的方式來處理寄宿圖的時候,一定要記住要手動的設(shè)置圖層的contentsScale屬性,否則,你的圖片在Retina設(shè)備上就顯示得不正確啦。代碼如下:
<pre>
layer.contentsScale = [UIScreen mainScreen].scale;
</pre>

以上是對寄宿圖的簡單介紹,下面就介紹主題 <code>- drawRect:</code>。
給 contents 賦值(CGImage)并不是唯一設(shè)置寄宿圖的方法,我們也可以通過用 Core Graphics 直接繪制寄宿圖,能夠通過繼承 UIView 并實現(xiàn)<code>- drawRect:</code>來自定義繪制。

<code>- drawRect:</code> 方法沒有默認(rèn)實現(xiàn),因為對 UIView 來說,寄宿圖并不是必須的。如果 UIView 檢測到 <code>- drawRect:</code> 方法被調(diào)用了,它就會為視圖分配一個寄宿圖,這個寄宿圖的大小的尺寸等于視圖大小乘以 contentScale 的積。

<b>所以在不需要使用寄宿圖的時候,就不要創(chuàng)建<code>- drawRect:</code>方法,會導(dǎo)致 CPU 和內(nèi)存資源的浪費(fèi),因此在沒有自定義繪制任務(wù)的 UIView 子類中不要寫一個空的<code>- drawRect:</code>方法</b>

在視圖顯示到屏幕上時,<code>- drawRect:</code>會被自動調(diào)用,并且當(dāng)一些表現(xiàn)效果的屬性值被修改時,一些視圖類型也會被重繪(如 bounds 屬性)。雖然<code>- drawRect:</code>是 UIView 的方法,但是還是底層的 CALayer 進(jìn)行了重繪的操作并保存了產(chǎn)生的寄宿圖。

CALayer 中設(shè)置寄宿圖的過程:首先 CALayer 會請求它的 CALayerDelegate 代理給它一個寄宿圖來顯示。它通過下面這個方法來實現(xiàn)獲取。
<pre>

  • (void)displayLayer:(CALayerCALayer *)layer;
    </pre>

如果代理不實現(xiàn)這個方法, CALayer 會轉(zhuǎn)而嘗試調(diào)用下面這個方法:
<pre>

  • (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
    </pre>

在調(diào)用這個方法之前,CALayer 創(chuàng)建了一個合適尺寸的空寄宿圖(尺寸由 bounds 和 contentsScale 決定)和一個 CoreGraphics 的繪制上下文環(huán)境,為繪制寄宿圖做準(zhǔn)備,他作為 ctx 參數(shù)傳入。

但是在使用這個方法時,不同于 UIView ,CALayer 不會自動重繪它的內(nèi)容,需要手動調(diào)用 <code>- display</code>。

總的來說,當(dāng)使用寄宿了視圖的圖層的時候,不必實現(xiàn)<code>- displayLayer:</code>和<code>- drawLayer: inContext:</code>方法來繪制寄宿圖。通常做法是實現(xiàn) UIView 的<code>- drawRect:</code>方法,UIView 會做完剩下的工作,包括在需要重繪的時候調(diào)用<code>- display</code>方法。

這是一篇關(guān)于 drawRect 的博文《內(nèi)存惡鬼 drawRect》 ,看完可以學(xué)到更多關(guān)于 drawRect 的知識。

NSTimer && CADisplayLink

NSTimer 是如何工作的?

當(dāng)設(shè)置一個 NSTimer 時,NSTimer 會被插入到當(dāng)前的 NSRunloop 中,然后直到指定的時間過去之后才會被執(zhí)行。但是什么時候啟動定時器并沒有上限,而且只有當(dāng) NSRunloop 的上一個任務(wù)結(jié)束之后才會被執(zhí)行,因此通常會導(dǎo)致不定時的延遲。 NSRunloop 主要爭對主線程,其中包含的任務(wù)有如下幾項:

  • 處理觸摸事件
  • 發(fā)送和接受網(wǎng)絡(luò)數(shù)據(jù)包
  • 執(zhí)行使用 GCD 的代碼
  • 處理計時器的行為
  • 屏幕重繪

因此屏幕重繪的頻率是60次/秒,但是和定時器一樣,如果上一次重繪執(zhí)行很長的時間,那么也會導(dǎo)致延遲。就不能保證定時器精準(zhǔn)的每一秒執(zhí)行60次。

對于動畫的實現(xiàn)可以通過以下這些途徑進(jìn)行優(yōu)化:

  • 可以用 CADisplayLink 讓更新頻率嚴(yán)格控制在每次屏幕刷新之后
  • 基于真實幀的持續(xù)時間而不是假設(shè)的更新頻率來做動畫
  • 調(diào)整動畫計時器的 RunLoop 模式,這樣就不會被別的事件干擾

用 CADisplayLink 而不是 NSTimer,會保證幀率足夠連續(xù),使得動畫看起來更加平滑,但即使 CADisplayLink 也不能保證每一幀都按計劃執(zhí)行,一些失去控制的離散的任務(wù)或者事件(例如資源緊張的后臺程序)可能會導(dǎo)致動畫偶爾地丟幀。

無論是使用 NSTimer 還是 CADisplayLink,我們?nèi)匀恍枰幚硪粠臅r間超出了預(yù)期的1/60秒。由于我們不能夠計算出一幀真實的持續(xù)時間,所以需要手動測量。我們可以在每幀開始刷新的時候用 CACurrentMediaTime() 記錄當(dāng)前時間,然后和上一幀記錄的時間去比較。


總結(jié)

在這個 Demo 里主要涉及了以上幾個知識點,通過 CAShapeLayer 來繪制整個臺子,然后通過實現(xiàn) <code>- drawLayer: inContext:</code> 實現(xiàn)橢圓進(jìn)度條的效果(在淘寶彩排H5里有個顏色漸變的過程,我沒有實現(xiàn))。通過這個小 Demo,鞏固了之前 iOS 動畫學(xué)習(xí)的知識,感覺寫動畫是一個很有趣的事情。當(dāng)然不得不說,這個看似簡單的小游戲,實際做起來邏輯還是有點復(fù)雜的~

相關(guān)資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,691評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,270評論 5 13
  • 書寫的很好,翻譯的也棒!感謝譯者,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢噓噓閱讀 2,439評論 0 6
  • 文/婉兮 1 和王瀚的這場相見蓄謀已久,下定決心卻只是三天前。 那晚詩雅穿了一條新裙子,花蝴蝶一般在各個房間穿梭,...
    婉xi閱讀 6,885評論 46 179
  • 晚飯后,我獨(dú)自走在市鎮(zhèn)廣場。雖然已經(jīng)是秋天,晚風(fēng)卻是悶熱的。路過昏黃的路燈,身影逐漸被拉長,而后消失不見。突然感覺...
    重生之夏閱讀 243評論 0 1

友情鏈接更多精彩內(nèi)容