Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 681 - Interface Builder, FaceView controller, Gestures, Multiple MVCs

講義5に入るのですが、前半は講義4の続きです。眉毛と目を閉じる機能を加えていきます。

Developing iOS 9 Apps with Swift - Free Course by Stanford on iTunes U

実は1つだけ講義4で忘れていたことがあります。パブリックな「var scale = 0.9」をFaceViewクラスコードの一番最初に記述しているのに組み込み忘れていました。

private var skullRadius: CGFloat {
    return min(bounds.size.width, bounds.size.height) / 2 * scale
}

これでスマイルフェイスのスケールを調整できます。実はパブリックなデータ、これは後で操作できるようにクラス宣言の冒頭にまとめます。

    var scale: CGFloat = 0.9
    var mouthCurvature: Double = 1.0
// 講義4までに組み込んだ変数

    var eyesOpen: Bool = false
    var eyeBrowTilt: Double = -0.5
// 講義5の冒頭で組み込む目の開閉と眉毛の動きを調整する変数

    var color = UIColor.blueColor()
    var lineWidth: CGFloat = 5.0
// ここまででハードコードになっている変数をまとめます。

ここれから目の開閉と眉毛を追加しますが、コードは講義4の応用なので自分でトライするといいでしょう。私は挫折しましたが(^_^;)

目の開閉は簡単です。目を閉じた状態は直線にすればいいので、pathForEye()メソッドを少し変更します。

private func pathForEye(eye: Eye) -> UIBezierPath
{
    let eyeRadius = skullRadius / Ratios.SkullRadiusToEyeRadius
    let eyeCenter = getEyeCenter(eye)
    if eyesOpen {
    return pathForCircleCenteredAtPoint(eyeCenter, 
                               withRadius: eyeRadius)
    } else {
        let path = UIBezierPath()
        path.moveToPoint(CGPoint(
                         x: eyeCenter.x - eyeRadius,
                         y: eyeCenter.y))
        path.addLineToPoint(CGPoint(
                            x: eyeCenter.x + eyeRadius, 
                            y: eyeCenter.y))
        path.lineWidth = lineWidth
        return path
    }
}

次は眉毛のチルトです。最初に眉毛をチルトさせるために直線に角度を加えていくやり方だと思いました。もっと簡単な方法で眉毛を動かしていました。両端のY軸方向だけ上下に動かすやり方です。確かに長さは変わるけどコーディングは楽ですね。こういう発想が直ぐ思いつかない固いオヤジ頭です(^_^;)

まずstaticな定数をStruct型のRatiosに加えます。

static let SkullRadiusToBrowOffSet: CGFloat = 6

そしてカスタムメソッドの「pathForBrow()」を用意します。

private func pathForBrow(eye: Eye) -> UIBezierPath {
    var tilt = eyeBrowTilt
    switch eye {
    case .Left: tilt *= -1.0
    case .Right: break
    }
    var browCenter = getEyeCenter(eye)
    browCenter.y -= skullRadius / Ratios.SkullRadiusToBrowOffSet
    let eyeRadius = skullRadius / Ratios.SkullRadiusToEyeRadius
    let tiltOffSet = CGFloat(max(-1, min(tilt, 1))) * eyeRadius / 2
    let browStart = CGPoint(x: browCenter.x - eyeRadius, 
                            y: browCenter.y - tiltOffSet)
    let browEnd = CGPoint(x: browCenter.x + eyeRadius, 
                          y: browCenter.y + tiltOffSet)
    let path = UIBezierPath()
    path.moveToPoint(browStart)
    path.addLineToPoint(browEnd)
    path.lineWidth = lineWidth
    return path
}

そしてdrawRect()メソッドを次のようにします。

override func drawRect(rect: CGRect) {
    color.set()
    pathForCircleCenteredAtPoint(skullCenter, 
                 withRadius: skullRadius).stroke()
    pathForEye(.Left).stroke()
    pathForEye(.Right).stroke()
    pathForMouth().stroke()
    pathForBrow(.Left).stroke()
    pathForBrow(.Right).stroke()
}

既にカスタムメソッドでも書き換えられていますが、ハードコーディング*1を排除しています。

これをランすると次のようになりました。
f:id:yataiblue:20160520154841j:plain
次はXcodeのInterface Builderの便利な機能を紹介しています。これは2年前と同様なので関連記事を見て下さい。Xcodeショートカットのページに情報を追記します。

  1. @IBDesignable -> Swiftで遊ぼう! - 257 - ポール先生の講義はやっとLecture 6に進む @IBDesignable - Swiftで遊ぼう! on Hatena
  2. @IBInspectable -> Swiftで遊ぼう! - 258 - Xcode6.2のチップ @IBInspectable - Swiftで遊ぼう! on Hatena

今日はこれだけ。

*1:ハードコード値とは次のページの後半に説明があります -> Swiftで遊ぼう! - 371 - Developing iOS Apps (Swift) Implement a Custom Control - Swiftで遊ぼう! on Hatena