こちらを参考にしました。
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に描画します。
以上。