HSStockChart:用 Swift 繪製股票分時圖、K 線圖

漢森發表於2018-01-04

HSStockChart

HSStockChart 是一個繪製股票分時圖、K 線圖的庫。支援流暢的回彈拖動,長按十字線,捏合放大縮小等功能,主要使用了 CAShapeLayer 來繪圖,相比使用 Core Graphics 和重寫 drawRect 的方法更高效,佔用記憶體更小。

HSStockChart:用 Swift 繪製股票分時圖、K 線圖

GitHub地址:HSStockChart

Features

  • 支援繪製分時圖,五日分時圖,K 線圖,MA 線指標,交易量柱等。
  • 支援橫屏檢視。
  • K 線圖利用 UIScrollView 達到流暢的滑動檢視效果。
  • 使用 CAShapeLayer 繪圖,記憶體佔用更小,效率更高。

Explain

  1. 之前繪圖的方法是重寫 drawRect 方法,在方法裡獲取 CGContext 然後利用Core Graphics 來進行繪圖,呼叫 setNeedsDisplay 來重新整理。但是這種方法有個問題是:

一旦你實現了 CALayerDelegate 協議中的 -drawLayer:inContext: 方法或者 UIView 中的 -drawRect: 方法(其實就是前者的包裝方法),圖層就建立了一個繪製上下文,這個上下文需要的記憶體可從這個公式得出:圖層寬x圖層高x4位元組,寬高的單位均為畫素。對於一個在 Retina iPad 上的全屏圖層來說,這個記憶體量就是 2048x1526x4位元組,相當於12MB記憶體,圖層每次重繪的時候都需要重新抹掉記憶體然後重新分配。【摘自 iOS Core Animation- Advanced Techniques 中文譯本 高效繪圖一章】

因為我要達到流暢滑動檢視的效果,所以在 UIScrollView 上新增了一個 UIView 這個 View 的寬度會依據當前展示資料的多少而變化,結合 UIScrollViewContentSize 就能達到很好的滑動效果。

HSStockChart:用 Swift 繪製股票分時圖、K 線圖

如果我用之前重寫 drawRect 的方法,那麼這個 View 會根據資料量的變大而變大,從而導致繪圖記憶體急劇上升,資料量大的時候會崩潰。基於此,我採用了 CAShapeLayer 的方式繪圖,此方式的特點如下:

CAShapeLayer 是一個通過向量圖形而不是 bitmap 來繪製的圖層子類。你指定諸如顏色和線寬等屬性,用 CGPath 來定義想要繪製的圖形,最後就自動渲染出來了。當然,你也可以用 Core Graphics 直接向原始的內容中繪製一個路徑,相比之下,使用 CAShapeLayer 有以下一些優點:

  • 渲染快速。CAShapeLayer 使用了硬體加速,繪製同一圖形會比用 Core Graphics 快很多。
  • 高效使用記憶體。一個 CAShapeLayer 不需要像普通 CALayer 一樣建立一個寄宿圖形,所以無論有多大,都不會佔用太多的記憶體。
  • 不會被圖層邊界剪裁掉,一個 CAShapeLayer 可以在邊界之外繪製。你的圖層路徑不會像在使用 Core Graphics 的普通 CALayer 一樣被剪裁掉。
  • 不會出現畫素化。當你給 CAShapeLayer 做3D變換時,它不像一個有寄宿圖的普通圖層一樣變得畫素化
  1. 自定義 CAShapeLayer,重寫 action(forKey event: String) 方法。目的是 關閉 CAShapeLayer 的隱式動畫,避免滑動時候或者十字線出現時有殘影的現象(實際上是因為 Layer 的 position 屬性變化而產生的隱式動畫)

    class HSCAShapeLayer: CAShapeLayer {
        override func action(forKey event: String) -> CAAction? {
            return nil
        }
    }
    複製程式碼

Contact

我的部落格:myhanson.com
GitHub地址:HSStockChart
如果使用中發現問題歡迎新增 issue ,也歡迎 Pull request。

相關文章