LoginSignup
4
4

More than 5 years have passed since last update.

Panジェスチャ後のvelocityを利用した放物線アニメーション

Posted at

UIPanGestureRecognizerで指が離されたときのvelocityを使って曲線移動するのアニメーションを作ります。

circle.gif

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()
    }
}

4
4
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
4
4