CAShapeLayer繪制波浪進度動畫

本篇主要介紹CAShapeLayer以及與path的配合使用

一、CAShapeLayer

首先我們先介紹一下CAShapeLayer這個類:

1、CAShapeLayer繼承自CALayer

2撤蟆、CAShapeLayer需要與Path(不論是CGMutablePath還是UIBezierPath)一起使用

3郊霎、使用CAShapeLayer與Path可以實現(xiàn)不在view的drawRect方法中畫出有一些想要的圖形

4贼邓、CAShapeLayer屬于CoreAnimation框架,其動畫渲染直接提交到手機的GPU當中润绵,相較于view的drawRect方法使用CPU渲染而言,其效率極高该酗,能大大優(yōu)化內(nèi)存使用情況授药。

下面是CAShapeLayer的一些屬性

動畫路徑,由若干個點構(gòu)成

open var path: CGPath?

路徑填充的顏色,注意與邊框線的區(qū)分

open var fillColor: CGColor?

填充規(guī)則

open var fillRule: String

這個填充規(guī)則有下面兩個選項:

public let kCAFillRuleNonZero: String

public let kCAFillRuleEvenOdd: String

可能有同學對這兩個屬性有疑問,我來詳細解釋一下

比如說一個圖形a是一個圓,在a的內(nèi)部有一個三角形b

fiiRule是默認屬性kCAFillRuleNonZero時,那就是正常顯示一個圓,內(nèi)部有一個三角形


kCAFillRuleNonZero

kCAFillRuleEvenOdd則會把屬于a內(nèi)部的點給扣掉,形成一個中空的部分


kCAFillRuleEvenOdd

那為什么要叫做"奇偶"呢,這與判斷點是否屬于內(nèi)部的條件有關(guān):

選取一個點向任意方向畫一條射線,如果與兩條path的交點為偶數(shù),則屬于內(nèi)部,會被扣掉;與path的焦點為奇數(shù),則在中間部分

順帶解釋一下kCAFillRuleNonZero的判斷條件:

選取一個點向任意方向畫一條射線,當射線通過path時,path從左向右則加1,path從右向左則-1,當計數(shù)不為0時,這個點則在path內(nèi),所以叫做NonZero

邊線顏色

open var strokeColor: CGColor?

下面兩個屬性可以放在一起介紹,一個是開始點,一個是結(jié)束點,是CGFloat類型的百分比數(shù)值

可以通過設(shè)置這兩個屬性,對path進行分區(qū)顯示和動畫顯示

open var strokeStart: CGFloat

open var strokeEnd: CGFloat


strokeStart = 0.1; strokeEnd = 0.7

邊線寬度

open var lineWidth: CGFloat


線端類型


open var lineCap: String

一圖秒懂系列

lineCap

路徑相交樣式

open var lineJoin: String

/* `lineJoin' values. */

public let kCALineJoinMiter: String

public let kCALineJoinRound: String

public let kCALineJoinBevel: String

一圖秒懂系列


lineJoin

最大斜接長度(只有l(wèi)ineJoin設(shè)置為kCALineJoinMiter時有效)

open var miterLimit: CGFloat

那什么是斜街長度呢,當兩條不平行的線段相連時,較小角度的內(nèi)連點與較大角度的外連點之間的距離,就像上圖第一個線條上兩個直角的定點之間的距離,當超過最大斜接長度時,系統(tǒng)會默認使用kCALineJoinBevel來畫線

線性模版

open var lineDashPattern: [NSNumber]?

為了理解這個屬性,參考了官方例子進行了測試

let lineDashPatterns: [[NSNumber]?]? = [nil, [5,5,10], [10, 5, 5, 5]]

for (index, lineDashPattern) in lineDashPatterns.enumerated() {

? ? ? ? let shapeLayer = CAShapeLayer()

? ? ? ? shapeLayer.strokeColor = UIColor.black.cgColor

? ? ? ? shapeLayer.lineWidth = 5

? ? ? ? shapeLayer.lineDashPattern = lineDashPattern

? ? ? ? let path = CGMutablePath()

? ? ? ? let y = CGFloat(index * 50)

? ? ? ? path.addLines(between: [CGPoint(x: 0, y: y+50),

? ? ? ? CGPoint(x: 640, y: y+50)])

? ? ? ? shapeLayer.path = path?

? ? ? ? self.view.layer.addSublayer(shapeLayer)

}

lineDashPattern傳入一個數(shù)組(默認為nil),奇數(shù)位的數(shù)字表示著色片段的長度,偶數(shù)位表示未著色片段的長度

如果數(shù)組只有奇數(shù)個成員,則最后一個數(shù)字也默認是最后一段未著色線段的長度(因為著色片段后必須有一段未著色片段)

lineDashPattern

線型模版的起始位置

open var lineDashPhase: CGFloat

舉上面這張圖第三條線的例子,如果lineDashPhase設(shè)置為10,則path會從第10個單位長度開始繪制,就是第一段長線段的末尾開始,先是長度為5的空白,然后長度為5的線段,長度為5的空白,長度為10的線段,最后依次.....

二、繪制波浪

不管你是用什么方法繪制path,無非是通過添加一個個點到path上,然后把path交給CAShapeLayer進行繪制

在這里,我使用正弦曲線進行繪制

mWavePathFir.removeAllPoints()

mWavePathFir.move(to: CGPoint.init(x: 0, y: self.frame.size.height))

//正弦坐標

for i in 0...Int(self.frame.size.width-1) {

let x = Double.pi*Double(i)/Double(self.frame.size.width)*2

let y = Double(offset)*Double.pi/Double(self.frame.size.width)

let z = waveHeight!*CGFloat(sinf(Float(x+y))) + waveHeightOffset!*(1-progress)

mWavePathFir.addLine(to: CGPoint(x: CGFloat(i), y: CGFloat(z)))

}

mWavePathFir.addLine(to: CGPoint.init(x: self.frame.size.width, y: self.frame.size.height))

mWaveLayerFir.path = mWavePathFir.cgPath

然后通過CADisplayLink設(shè)置YYJWaveProgress的progress來控制進度動畫

link = CADisplayLink.init(target: self, selector: #selector(self.setProgress))

link?.add(to: RunLoop.main, forMode: RunLoopMode.commonModes)

link?.isPaused = false


demo



具體使用可參考我的github上的demo

我的github

喜歡這篇文章的小伙伴,歡迎點贊和小星星哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呜魄,一起剝皮案震驚了整個濱河市悔叽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爵嗅,老刑警劉巖娇澎,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異睹晒,居然都是意外死亡趟庄,警方通過查閱死者的電腦和手機括细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事具被。” “怎么了览濒?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拖云。 經(jīng)常有香客問我贷笛,道長,這世上最難降的妖魔是什么宙项? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任乏苦,我火速辦了婚禮,結(jié)果婚禮上尤筐,老公的妹妹穿的比我還像新娘汇荐。我一直安慰自己,他們只是感情好盆繁,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布拢驾。 她就那樣靜靜地躺著,像睡著了一般改基。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咖为,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天秕狰,我揣著相機與錄音,去河邊找鬼躁染。 笑死鸣哀,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的吞彤。 我是一名探鬼主播我衬,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饰恕!你這毒婦竟也來了挠羔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤埋嵌,失蹤者是張志新(化名)和其女友劉穎破加,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雹嗦,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡范舀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年合是,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锭环。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡聪全,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辅辩,到底是詐尸還是另有隱情难礼,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布汽久,位于F島的核電站鹤竭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏景醇。R本人自食惡果不足惜臀稚,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望三痰。 院中可真熱鬧吧寺,春花似錦、人聲如沸散劫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽获搏。三九已至赖条,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間常熙,已是汗流浹背纬乍。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裸卫,地道東北人仿贬。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像墓贿,于是被迫代替她去往敵國和親茧泪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容