iOS端K線系列之繪制方法比較(CoreGraphics弯菊、CoreAnimation)

寫在前面

關(guān)于在IOS端進(jìn)行原生界面繪制轰传,蘋果開發(fā)文檔里明確提供了幾種方法:

  1. 使用系統(tǒng)提供的標(biāo)準(zhǔn)視圖盗扒,例如lists, collections, alerts, images, progress bars, tables等。
  2. 使用Core Animation的圖層刨啸,Core Animation不僅提供了動(dòng)畫的類堡赔,還提供了顯示內(nèi)容的圖層類。
  3. 使用OpenGL ES设联,這個(gè)框架提供了一套開放標(biāo)準(zhǔn)的圖形繪制庫(kù)善已,主要面向游戲開發(fā)或者需要高幀速率的app。
  4. 使用UIWebView類展示基于web的圖形界面离例。

很顯然换团,如果你要開發(fā)一套K線框架:

  • 第一種方法肯定不適合,因?yàn)槟銢]辦法去用標(biāo)準(zhǔn)的控件來顯示K線宫蛆;
  • 第四種使用webview艘包,這樣的話就需要使用百度的echarts,或者還可以使用highcharts
  • 所以耀盗,想要開發(fā)原生K線想虎,就只能選擇第二種和第三種方法了
  • OpenGL ES框架使用起來比較麻煩,后續(xù)會(huì)單獨(dú)在一篇文章中介紹如何使用
  • 所以叛拷,在這里舌厨,就只介紹第二種方法,也就是使用Core Animation
  • 其實(shí)忿薇,還有一種辦法裙椭,就是繞過Core Animation躏哩,直接使用Core Graphics進(jìn)行繪制。這個(gè)在后面會(huì)說到揉燃。

Core Animation是什么?

在蘋果的開發(fā)文檔中扫尺,有關(guān)于Core Animation的介紹,點(diǎn)擊這兒你雌。

這里放一張非常經(jīng)典的圖:


Core Animation是一個(gè)圖形渲染和動(dòng)畫的基礎(chǔ)庫(kù)器联,是一個(gè)復(fù)合引擎,職責(zé)就是盡可能快地組合屏幕上不同的可視內(nèi)容婿崭,這個(gè)內(nèi)容是被分解成獨(dú)立的圖層拨拓,存儲(chǔ)在一個(gè)叫圖層樹的體系之中。
Core Animation可以直接用在Max OS X和IOS平臺(tái)上氓栈。
Core Animation的動(dòng)畫執(zhí)行過程都是在后臺(tái)操作的渣磷,不會(huì)阻塞主線程。
Core Animation是直接作用于CALayer授瘦,并非直接作用于UIView醋界。
Core Animation有以下幾個(gè)分類:

  • 提供顯示內(nèi)容的圖層類
  • 動(dòng)畫和計(jì)時(shí)類
  • 布局和約束類
  • 事務(wù)類,在原子更新的時(shí)候組合圖層類

CoreAnimation使用

在繪制K線時(shí)提完,主要是使用CALayer的子類CAShapeLayer形纺,它是一個(gè)通過矢量圖形而不是bitmap來繪制的圖層子類。使用時(shí)徒欣,可以直接指定諸如顏色和線寬等屬性逐样,用CGPath來定義線稿繪制的圖形,最后CAShapeLayer就自動(dòng)渲染出來了打肝。
首先先從最簡(jiǎn)單的開始脂新,畫一條線,代碼如下:

    //初始化一個(gè)線的圖層
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    //初始化一個(gè)描述的路徑
    UIBezierPath *linePath = [UIBezierPath bezierPath];
    //設(shè)置線段開始的點(diǎn)
    [linePath moveToPoint:beginPoint];
    //設(shè)置線段結(jié)束的點(diǎn)
    //這里也可以添加多個(gè)點(diǎn)
    [linePath addLineToPoint:endPoint];
    //設(shè)置圖層路徑
    lineLayer.path = linePath.CGPath;
    //設(shè)置圖層的其他屬性
    lineLayer.lineWidth = lineWidth;
    lineLayer.strokeColor = lineColor.CGColor;
    lineLayer.fillColor = [UIColor clearColor].CGColor;

執(zhí)行結(jié)果如下:


從代碼上可以看到粗梭,繪制線段的步驟很簡(jiǎn)單:

  1. 初始化一個(gè)圖層
  2. 初始化用戶線段的路徑
  3. 添加線段開始的坐標(biāo)點(diǎn)
  4. 再添加多個(gè)中間的坐標(biāo)點(diǎn)
  5. 最后添加結(jié)束的坐標(biāo)點(diǎn)
  6. 把路徑設(shè)置到圖層上去
  7. 設(shè)置圖層的各個(gè)屬性

其實(shí)現(xiàn)在再想一想K線中的分時(shí)線(如果不了解争便,可以點(diǎn)擊這兒),可以直接用這段代碼來繪制出來断医,當(dāng)然滞乙,不包括分時(shí)線下方的背景顏色,并且得添加多個(gè)坐標(biāo)點(diǎn)孩锡。
畫完一條線后酷宵,再來畫一個(gè)方塊:

    //初始化一個(gè)rect
    CGRect frameRect = CGRectMake(x, y, width, height);
    //初始化一個(gè)圖層
    CAShapeLayer *layer = [CAShapeLayer layer];
    //初始化一個(gè)描述框的路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:frameRect];
    //把路徑設(shè)置到圖層中
    layer.path = path.CGPath;
    //設(shè)置圖層的各個(gè)屬性
    layer.strokeColor = strokeColor.CGColor;
    layer.fillColor = backColor.CGColor;

執(zhí)行結(jié)果如下:


繪制的步驟也很簡(jiǎn)單:

  1. 設(shè)置好框的frame
  2. 然后初始化路徑的時(shí)候,直接把框的frame賦值進(jìn)去
  3. 初始化一個(gè)圖層
  4. 把路徑設(shè)置到圖層中
  5. 設(shè)置圖層的各個(gè)屬性

在這里躬窜,如果留心一下浇垦,其實(shí)就可以想到,框已經(jīng)繪制好了荣挨,那一個(gè)蠟燭也就繪制好了男韧,那繪制多個(gè)框朴摊,一整屏的蠟燭圖不就繪制出來了。(沒留心的此虑,可以點(diǎn)這兒)如果你已經(jīng)理解了上面所說的甚纲,那么我們?cè)贙線框架開發(fā)的道路上已經(jīng)走出一大步。

Core Graphics的使用

上面有第一個(gè)地方說到朦前,繪制界面除了使用Core Animation以外介杆,還可以繞過Core Animation直接使用OpenGL ES或者Core Graphics。

在這里韭寸,介紹一下Core Graphics春哨。Core Graphics是一套基于C的API框架,使用了Quartz作為繪圖引擎恩伺。它提供了低級(jí)別赴背、輕量級(jí)、高保真度的2D渲染晶渠。該框架可以用于基于路徑的繪圖凰荚、變換、顏色管理褒脯、脫屏渲染便瑟,模板、漸變番川、遮蔽胳徽、圖像數(shù)據(jù)管理、圖像的創(chuàng)建爽彤、遮罩以及PDF文檔的創(chuàng)建、顯示和分析缚陷。
和上面一樣适篙,也是從最基礎(chǔ)的一條線開始:

    //獲取當(dāng)前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //開始記錄路徑
    CGContextBeginPath(ctx);
    //設(shè)置開始坐標(biāo)點(diǎn)
    CGContextMoveToPoint(ctx, beginPoint);
    //添加坐標(biāo)點(diǎn),或者也可以只添加一個(gè)坐標(biāo)點(diǎn)
    CGContextAddLineToPoint(ctx, endPoint);
    //結(jié)束記錄路徑
    CGContextClosePath(ctx);
    //設(shè)置線段寬度
    CGContextSetLineWidth(ctx, lineWidth);
    //設(shè)置顏色
    CGContextSetStrokeColorWithColor(ctx, lineColor.CGColor);
    //開始繪制路徑
    CGContextStrokePath(ctx);

執(zhí)行效果和上面使用CAShapeLayer繪制線段的效果一樣箫爷。

依次類推嚷节,可以繪制一條線,也就可以繪制一個(gè)框虎锚。

這里說明一下硫痰,代碼中的CGContext 上下文定義了繪制的地方。在使用UIKit時(shí)窜护,上下文是唯一的效斑,UIKit會(huì)維護(hù)著一個(gè)上下文堆棧,而UIKit方法總是繪制到最頂層的上下文中柱徙。

一般使用Core Graphics進(jìn)行繪制缓屠,都會(huì)重寫drawRect方法奇昙,所以這里的上下文就是上下文堆棧最頂層的上下文,使用UIGraphicsGetCurrentContext就可以獲取到敌完。

兩者比較

這里總結(jié)一下储耐,上述介紹了兩種繪制圖形的方式:

  1. 使用Core Animation的 CAShapeLayer圖層子類
  2. 使用Core Graphics

那兩種方式有什么區(qū)別呢?

1. CAShapeLayer渲染更快速滨溉。因?yàn)樗褂昧擞布铀偈蚕妫L制同一圖形會(huì)比用Core Graphics快很多。
2. CAShapeLayer更高效使用內(nèi)存晦攒。一個(gè)CAShapeLayer不需要像普通CALayer一樣創(chuàng)建一個(gè)寄宿圖形闽撤,所以無論有多大,都不會(huì)占用太多的內(nèi)存勤家。
3. CAShapeLayer不會(huì)被圖層邊界剪裁掉腹尖,一個(gè) CAShapeLayer 可以在邊界之外繪制。你的圖層路徑不會(huì)像在使用 Core Graphics 的普通 CALayer 一樣被剪裁掉伐脖。
4. CAShapeLayer不會(huì)出現(xiàn)像素化热幔。當(dāng)你給 CAShapeLayer 做3D變換時(shí),它不像一個(gè)有寄宿圖的普通圖層一樣變得像素化讼庇。

其實(shí)最后一點(diǎn)最關(guān)鍵绎巨,因?yàn)樗梅狭薑線框架開發(fā)的業(yè)務(wù)需求。

一旦你實(shí)現(xiàn)了 CALayerDelegate 協(xié)議中的 -drawLayer:inContext: 方法或者 UIView 中的 -drawRect: 方法(其實(shí)就是前者的包裝方法)蠕啄,圖層就創(chuàng)建了一個(gè)繪制上下文场勤,這個(gè)上下文需要的內(nèi)存可從這個(gè)公式得出:圖層寬x圖層高x4字節(jié),寬高的單位均為像素歼跟。對(duì)于一個(gè)在 Retina iPad 上的全屏圖層來說和媳,這個(gè)內(nèi)存量就是 2048x1526x4字節(jié),相當(dāng)于12MB內(nèi)存哈街,圖層每次重繪的時(shí)候都需要重新抹掉內(nèi)存然后重新分配留瞳。

而當(dāng)我們使用K線的時(shí)候,左滑或者右滑時(shí)骚秦,都會(huì)觸發(fā)重新繪制她倘,而每次重繪時(shí)都會(huì)重新獲取一個(gè)繪制上下文。而左滑或者右滑時(shí)作箍,會(huì)高頻率的進(jìn)行重繪硬梁,所以避免不了內(nèi)存的重新分配。

當(dāng)然胞得,這里也不是說Core Graphics效率就很差荧止,只是恰好在這樣的業(yè)務(wù)需求下,會(huì)把某一個(gè)問題放大。并且罩息,不要忘了CAShapeLayer繪制的圖形是直接操作layer嗤详,不會(huì)作用于UIView,更不會(huì)去響應(yīng)用戶的交互瓷炮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末葱色,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子娘香,更是在濱河造成了極大的恐慌苍狰,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烘绽,死亡現(xiàn)場(chǎng)離奇詭異淋昭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)安接,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門翔忽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盏檐,你說我怎么就攤上這事歇式。” “怎么了胡野?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵材失,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我硫豆,道長(zhǎng)龙巨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任熊响,我火速辦了婚禮旨别,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汗茄。我一直安慰自己昼榛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布剔难。 她就那樣靜靜地躺著,像睡著了一般奥喻。 火紅的嫁衣襯著肌膚如雪偶宫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天环鲤,我揣著相機(jī)與錄音纯趋,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吵冒,可吹牛的內(nèi)容都是我干的纯命。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼痹栖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼亿汞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起揪阿,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤疗我,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后南捂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吴裤,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年溺健,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了麦牺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鞭缭,死狀恐怖剖膳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缚去,我是刑警寧澤潮秘,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站易结,受9級(jí)特大地震影響枕荞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搞动,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一躏精、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鹦肿,春花似錦矗烛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涣旨,卻和暖如春歪架,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背霹陡。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工和蚪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留止状,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓攒霹,卻偏偏與公主長(zhǎng)得像怯疤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子催束,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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