[iOS] Core Animation のグラフィックス関連をメソッドチェーンで書けるライブラリを作ってみた

2019.03.23

こんにちは。きんくまです。

ちょっと前にCALayerのことについて記事を書きました。
[iOS] CALayerを使ってグラフィック操作で遊んでみよう!

今回はその続きで、CoreAnimationのグラフィックス関連をメソッドチェーンで書けるライブラリを作ってみたです。

作ったもの
KinkumaDesign/SimpleCAGraphics: Easy access to Core Animation graphics

どんなもの?

特徴は2つあります。

  • メソッドチェーンで書ける
  • CGFloatではなくて、SwiftネイティブのDoubleかFloat型で引数を入れられる

メソッドチェーンって?

let layerController = LayerController()
layerController.setFrame(x: 0, y: 0, width: 100, height: 70)
    .translate(x: 100, y: 100)
    .setBackgroundColor(.red)
    .setOpacity(0.5)
view.layer.addSublayer(layerController.layer)

メソッドチェーンは、古くはjQueryみたいに、メソッドの返り値がそのオブジェクト自身になっているので、続けてメソッドを書けるやつです。

CGFloatじゃなくてDoubleかFloat型

CoreAnimationの引数はCGFloat型のものが多いのですが、DoubleかFloatで入れられるようにしました。

layerController.setFrame(x: 0, y: 0, width: 100, height: 80)
    .translate(x: 40, y: 30)

ただ、CGFloat型でも入れられた方が便利だったので、そういう場合は、メソッド名の最後にCGをつければ入れられます。
オーバーロードで同じメソッド名でもやってみたのですが、そうすると数値を直接入れた場合にコンパイラがどっちの型なのかわからないよー!となってしまったので、明確にメソッド名は分けました。

layerController.setFrameCG(x: 0, y: 0, width: 100, height: 80)
    .translateCG(x: 40, y: 30)

インストール方法

CarthageCocoaPods に対応しました。
インストール方法はReadmeをご覧ください。基本的に他のライブラリと同じです。

ただ、CocoaPodsは登録していない野良Podになります、、。

LayerController

ライブラリの作りなのですが、CALayerに直接Extensionを書くのではなくて、LayerControllerというクラスを作り、そこ経由でCALayerにアクセスするようにしてあります。

LayerControllerとCALayerの関係が、ViewControllerとViewの関係のような感じです。

見た目

let layerController = LayerController()
layerController.setOpacity(0.5)
    .setCornerRadius(8)
    .setBackgroundColor(.red)
    .setFrame(x: 100, y: 20, width: 100, height: 80)

canvasView.layer.addSublayer(layerController.layer)

移動・拡大・回転

let layerController = LayerController()
let color = HexColor.createColor("#70aeed")
layerController.setBackgroundColor(color)
    .setFrame(x: 0, y: 0, width: 100, height: 80)
    .translate(x: 100, y: 100)
    .rotate(radian: .pi / 4)
    .scale(scaleX: 1.5, scaleY: 1.5)

canvasView.layer.addSublayer(layerController.layer)

画像

guard let smileImage = UIImage(named: "smile"),
    let leftArrowImage = UIImage(named: "leftArrow") else { return }
let layerController = LayerController()
layerController.setImage(smileImage)
    .translate(x: 10, y: 300)
canvasView.layer.addSublayer(layerController.layer)

let layerController2 = LayerController()
layerController2.setImage(leftArrowImage)
    .translate(x: 160, y: 300)
canvasView.layer.addSublayer(layerController2.layer)

上のサンプルを書くと、冒頭に載せたようなこんな感じになります。

その他のクラス

その他のクラスを全て書くと長くなっちゃうので、リンクだけ。

GraphicsLayerControllerを使ったサンプルです。

let graphicsController = GraphicsLayerController()
view.layer.addSublayer(graphicsController.layer)
let centerPoint = CGPoint(x: 150, y: 150)

let yellow = HexColor.createColor("#ffef37")
let brown = HexColor.createColor("#9b874a")

// base
graphicsController.setStrokeColor(brown)
    .setFillColor(yellow)
    .setLineWidth(18)
    .drawCircleCG(x: centerPoint.x, y: centerPoint.y, radius: 80)

// eye
graphicsController.setStrokeColor(nil)
    .setFillColor(brown)
    .setLineWidth(0)
    .drawCircleCG(x: centerPoint.x - 30, y: centerPoint.y - 20, radius: 15)
    .drawCircleCG(x: centerPoint.x + 30, y: centerPoint.y - 20, radius: 15)

// mouth
graphicsController.setStrokeColor(brown)
    .setFillColor(nil)
    .setLineWidth(10)
    .drawArcDegreeCG(newPath: true,
                   x: centerPoint.x,
                   y: centerPoint.y,
                   radius: 45,
                   startAngleDegree: 90 - 70,
                   endAngleDegree: 90 + 70)

実際のサンプル - 棒グラフ

実はなんでこのライブラリを作ってみたかといいますと、グラフをSwiftで書いてみたいなーと思いまして。

サンプルだとこんな感じになります。

ソースコードはこんな感じです。

D3.jsというJavaScriptのライブラリがあります。
D3.js - Data-Driven Documents

これの棒グラフの書き方を参考にしています。

円グラフや折れ線グラフなど、いくつかの種類のグラフを作ってみたことがあるのですが、だいたいやり方は同じだったので、次回のブログ記事は棒グラフの作り方を通して、グラフ描画の考え方や手順を書いてみたいなーと思っています。
ではでは。