LoginSignup
63
62

More than 5 years have passed since last update.

CAKeyframeAnimationを使ってUIBezierPathをアニメーションさせる

Posted at

bezierPath1.gif
ベジェ曲線を引っ張って動かしてみました。

こちらを参考にしました。
https://www.youtube.com/watch?v=pTrW3cZg1YU
Desarrollo iOS 7: Core Animation: CAKeyFrameAnimation y mucho más

viewを追加

class sampleView: UIView,UIGestureRecognizerDelegate {
    var verticalLine:CAShapeLayer?
}

addGestureRecognizerを追加

func addPanGesture() {
    var sgr = UIPanGestureRecognizer(target: self, action: "handleSlide:")
    sgr.delegate = self
    self.addGestureRecognizer(sgr)
}

タッチ位置の変化量を取得

func handleSlide(gr:UIPanGestureRecognizer) {
    var amountX = gr.translationInView(self).x
    var amountY = gr.translationInView(self).y
    self.verticalLine?.path = self.getLinePathWithAmount(amountX: amountX, amountY: amountY)

    if gr.state == UIGestureRecognizerState.Ended {
        self.removeGestureRecognizer(gr)
        self.animateLineReturnFrom(positionX: amountX, positionY: amountY)
    }
}

今回はY方向の移動量しか使用していませんが、X方向の移動量も計算しています。

アニメーション定義

func animateLineReturnFrom(#positionX: CGFloat,positionY: CGFloat) {
    var bounce = CAKeyframeAnimation(keyPath: "path")
    bounce.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

    var values = [
        self.getLinePathWithAmount(amountX: positionX, amountY: positionY),
        self.getLinePathWithAmount(amountX: -(positionX * 0.7), amountY: -(positionY * 0.7)),
        self.getLinePathWithAmount(amountX: positionX * 0.4, amountY: positionY * 0.4),
        self.getLinePathWithAmount(amountX: -(positionX * 0.3), amountY: -(positionY * 0.3)),
        self.getLinePathWithAmount(amountX: positionX * 0.15, amountY: positionY * 0.15),
        self.getLinePathWithAmount(amountX: 0.0, amountY: 0.0)
    ]

    bounce.values = values
    bounce.duration = 0.9
    bounce.removedOnCompletion = false
    bounce.fillMode = kCAFillModeForwards
    bounce.delegate = self
    self.verticalLine?.addAnimation(bounce, forKey: "return")
}

配列valuesにベジェ曲線を追加します。すべての位置を追加するのはとても大変なのですが、CAKeyframeAnimationを使えばkeyframe間を補完してアニメーションしてくれます。

CAKeyframeAnimationとCABasicAnimationとの違いは以下の通り。

CAKeyframeAnimation
* 3つ以上の値を補完するアニメーション

CABasicAnimation
* 2つの値を補完するアニメーション

・参考
http://www.slideshare.net/nakiwo/cakeyframeanimation-25415214

ベジェ曲線を定義

func getLinePathWithAmount(#amountX:CGFloat,amountY:CGFloat) -> CGPathRef {
    let w = UIScreen.mainScreen().bounds.width
    let h = UIScreen.mainScreen().bounds.height
    let centerY = h / 2

    var bezierPath = UIBezierPath()

    var topLeftPoint = CGPointMake(0, centerY)
    var topMidPoint = CGPointMake(w / 2, centerY + amountY)
    var topRightPoint = CGPointMake(w, centerY)

    bezierPath.moveToPoint(topLeftPoint)
    bezierPath.addQuadCurveToPoint(topRightPoint, controlPoint: topMidPoint)

    return bezierPath.CGPath
}


CurrentPoint、Control Point,Endpointの関係はAppleのリファレンスを参考にしました。
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIBezierPath_class/#//apple_ref/occ/instm/UIBezierPath/addQuadCurveToPoint:controlPoint:

ベジェ曲線を描画する

func createLine() {
    verticalLine = CAShapeLayer(layer: self.layer)
    verticalLine?.lineWidth = 3.0
    verticalLine?.path = getLinePathWithAmount(amountX: 0.0, amountY: 0.0)
    verticalLine?.strokeColor = UIColor.whiteColor().CGColor
    verticalLine?.fillColor = UIColor.clearColor().CGColor

    self.layer.addSublayer(verticalLine)
}

CAShapeLayerに描画します。

以上。

63
62
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
62