この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
iOS 10 で新しく追加されたUIViewPropertyAnimatorによって、アニメーションロジックを簡単に記述することが可能になりました。
今回は、この記述要領について、覚書として纏めてみました。
なお、UIViewPropertyAnimatorについては、既に、ここDevelopers.IOで紹介されていますので、クラス構造や、全機能の体系については、下記を御覧ください。
[iOS 10][UIKit] 新しく加わった動的なアニメーション実装の方法とその周辺解説
2 Initializing a Property Animator
(1) 最も単純なアニメーション
ビューの中心位置を変更するアニメーションです。
let animator = UIViewPropertyAnimator(duration: 2.0,
curve: .linear){
kao.center = endPoint
}
animator.startAnimation()
上記の例では、パラメータにduration:(アニメーションの持続時間)及びcurve:(アニメーションカーブ)が指定されていますが、cueve:には、次の4つ(UIViewAnimationCurve列挙型)が指定可能です。
- .liner (直線)
- .easeIn (初めゆっくり)
- .easeInOut (初めと終わりがゆっくり)
- .easeOut (終わりゆっくり)
(2) 3次ベジェ曲線
先の例では、アニメーションカーブをUIViewAnimationCurveで指定しましたが、2点指定によるベジェ曲線で指定することも可能です。
let animator = UIViewPropertyAnimator(duration: 2.0,
controlPoint1: CGPoint(x: 0.1,y: 0.5),
controlPoint2: CGPoint(x: 0.5, y:0.2),
animations: {
kao.center = endPoint
})
animator.startAnimation()
(3) スプリングエフェクト
dampingRatioで0〜1の減衰値を指定することで、スプリングエフェクトを定義できます。
let animator = UIViewPropertyAnimator(duration: 2.0,
dampingRatio: 0.3,
animations: {
kao.center = endPoint
})
animator.startAnimation()
3 UIViewAnimating
(1) UIViewAnimatingState
UIViewPropertyAnimatorの継承元である、UIViewAnimatingでは、startAnimation()、pauseAnimation()、stopAnimation(_:)などのメソッドによってステータスを変更します。
ステータスには、以下の3つがあります。 * Inactive (非アクティブ) * Active(アクティブ) * Stopped(停止)
API Reference UIViewAnimatingより
(2) fractionComplete
fractionCompleteは、アニメーションの進行具合を0〜1で表現しています。 そして、これは、セッターとして利用することも可能です。
下記の例は、スライダーによって、アニメーションの進行具合を変更している様子です。アニメーションを開始していないので、ステータスは非アクティブのままです。
var animator:UIViewPropertyAnimator?
animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){
kao.center = endPoint
}
@IBAction func sliderValueChanged(_ sender: UISlider) {
self.animator?.fractionComplete = CGFloat(sender.value)
}
(3) isReversed
isReversedというプロパティをセットすることで、アニメーションはリバースします。 下記の例は、アニメーションが開始され、アクティブ状態のものをリバースしています。
var animator:UIViewPropertyAnimator?
animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){
kao.center = endPoint
}
animator?.startAnimation()
@IBAction func tapReverseButton(_ sender: Any) {
animator?.isReversed = (animator?.isReversed)! ? false : true
}
4 Modifying Animations
(1) 追加
UIViewPropertyAnimatorは、UIViewImplicitlyAnimatingプロトコルを採用しており、簡単にアニメーションを追加することが可能です。
下記は、addAnimations(_:)による初期化時の追加です。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){
kao.center = endPoint
}
animator.addAnimations{
kao.alpha = 0.0
}
animator.startAnimation()
(2) 遅延指定
addAnimations(_:delayFactor:)では、追加するアニメーションの開始時期を遅らせることも可能です。 次の例は、alpha値の変化開始を全体の90%のアニメーションが進行した以降に指定しています。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){
kao.center = endPoint
}
animator.addAnimations({
kao.alpha = 0.0
}, delayFactor: 0.9)
animator.startAnimation()
(3) 終了後
addCompletion(_:)は、アニメーション終了後の変化を指定します。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){
kao.center = endPoint
}
animator.addCompletion {_ in
kao.bounds = CGRect(x: 0, y: 0, width: 70, height: 70)
}
animator.startAnimation()
アニメーションの追加は、初期化時に限らず、実行中のアニメーションにも可能です。 この場合、残り時間をアニメーションの継続時間として直ちに実行されます。
5 UITimingCurveProvider
UIViewPropertyAnimatorのタイミング指定で使用されるUITimingCurveProviderとしてUISpringTimingParametersが利用可能です。
これを使用するとバネのようなアニメーションが簡単に作成できます。
@IBOutlet weak var kao: UIImageView!
var animator:UIViewPropertyAnimator?
var startPosition:CGPoint?
override func viewDidLoad() {
super.viewDidLoad()
self.startPosition = self.kao.center
self.kao.isUserInteractionEnabled = true
self.kao.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.dragKao)))
}
func dragKao(gesture: UIPanGestureRecognizer) {
// ImageViewの相対位置
let translation = gesture.translation(in: self.view)
// View内での絶対位置
var position: CGPoint = CGPoint(x: translation.x + self.startPosition!.x, y: translation.y + self.startPosition!.y)
switch gesture.state {
case .began:
if animator != nil && animator!.isRunning {
animator!.stopAnimation(false)
}
kao.center = position
case .changed:
kao.center = position
case .ended:
let v = gesture.velocity(in: kao)
let velocity = CGVector(dx: v.x / 500, dy: v.y / 500)
let springParameters = UISpringTimingParameters(mass: 30, stiffness: 800, damping: 100, initialVelocity: velocity)
animator = UIViewPropertyAnimator(duration: 0.0, timingParameters: springParameters)
animator!.addAnimations({
self.kao.center = self.view.center
})
animator!.startAnimation()
default: break
}
6 最後に
UIViewPropertyAnimatorを使用すると、アニメーションの組み合わせが、非常にシンプルに記述できるように感じました。 なんとかUITimingCurveProviderを使いこなして、自由にアニメーションを作れるようになりたいと思います。
7 参考資料
iOS10からのAnimationがいい感じ!
Designing Animations with UIViewPropertyAnimator in iOS 10 and Swift 3