팬 제스처 후 velocity를 이용한 포물선 애니메이션

UIPanGestureRecognizer 에서 손가락을 놓을 때 velocity 를 사용하여 곡선 이동하는 애니메이션을 만듭니다.



Swift 4.2
import UIKit

class ViewController: UIViewController {
    var animationSample: AnimationSample?
    override func viewDidLoad() {
        super.viewDidLoad()
        animationSample = AnimationSample(view: view)
    }
}

class AnimationSample {
    let view: UIView

    let circle: UIView = {
        let diameter: CGFloat = 120
        let view = UIView(frame: CGRect(
            x: 0,
            y: 0,
            width: diameter,
            height: diameter))
        view.layer.cornerRadius = diameter * 0.5
        view.backgroundColor = .blue
        return view
    }()

    init(view: UIView) {
        self.view = view
        view.addSubview(circle)
        circle.center = view.center
        let pan = UIPanGestureRecognizer(
            target: self,
            action: #selector(didPan(gesture:)))
        circle.addGestureRecognizer(pan)
    }

    @objc private func didPan(gesture: UIPanGestureRecognizer) {
        let location = gesture.location(in: nil)
        switch gesture.state {
        case .began:
            circle.layer.removeAnimation(forKey: "animation")
            UIView.animate(withDuration: 0.1) {
                self.circle.center = location
            }
        case .changed:
            circle.center = location
        case .ended, .failed, .cancelled:
            circle.center = location
            animate(velocity: gesture.velocity(in: nil))
            break
        case .possible:
            break
        }
    }

    func animate(velocity: CGPoint) {
        let speed: CGFloat = 0.5
        let startPoint = circle.center
        let endPoint = view.center
        let controlPoint = CGPoint(
            x: startPoint.x + velocity.x * speed,
            y: startPoint.y + velocity.y * speed)
        let animation = CAKeyframeAnimation(keyPath: "position")
        let path = CGMutablePath()
        path.move(to: startPoint)
        path.addQuadCurve(to: endPoint, control: controlPoint)
        animation.path = path
        animation.duration = 1.0
        animation.fillMode = .forwards
        animation.isRemovedOnCompletion = false
        CATransaction.begin()
        CATransaction.setCompletionBlock {
            self.circle.center = endPoint
        }
        circle.layer.add(animation, forKey: "animation")
        CATransaction.commit()
    }
}

좋은 웹페이지 즐겨찾기