🔥

アニメーションを実装する

2023/03/12に公開

UIKitの場合は、UIView.animate(withDuration:animations:completion:)UIView.perform(_on:options:animations:completion:)などのブロック構文を用いたメソッドでアニメーションを実現していました。

この記事では、AppKitでのアニメーション実装方法の中からいくつかを紹介します。

実装方法

プロパティ1つだけの場合

animator()を利用できます。

例えば、NSSplitViewを使ってPaneのトグル挙動をアニメーション付きで実現する場合なら、以下のように実装します。

@objc func togglePane(sender: Any?) {

    paneSplitItem.animator().isCollapsed.toggle()

}

twitterで@dy4_268さんに教えて頂きました!ありがとうございます!
https://twitter.com/dy4_268/status/1613423855107985411?s=20&t=o8ajaWGAIsgoWcidw9FVYg

2つ以上のプロパティを同時にアニメーションさせたい場合

NSAnimationContextが利用できます。このオブジェクトはNSGraphicContextのようなAPIでアニメーション操作を行います。以下のように実装します。

  1. currentコンテキストの取得
  2. allowsImplicitAnimationtrueにセット
  3. アニメーションさせたいプロパティの変更
  4. allowsImplicitAnimationfalseにセット

例えば、NSSplitViewを使ってPaneのトグル挙動をアニメーション付きで実現する場合なら、以下のように実装します。

@objc func togglePane(sender: Any?) {

    let context = NSAnimationContext.current
    context.allowsImplicitAnimation = true
    paneSplitItem.isCollapsed.toggle()
    context.allowsImplicitAnimation = false

}

何度もこれを書くのは大変なので、CotEditorでは以下のように独自のブロックAPIを実装して使っているようです。

func withAnimation(_ animate: Bool = true, execute block: () -> Void) {
        
    let allowsImplicitAnimation = self.allowsImplicitAnimation
        
    self.allowsImplicitAnimation = animate
        
    block()
        
    self.allowsImplicitAnimation = allowsImplicitAnimation
}

(引用: https://github.com/coteditor/CotEditor/blob/3a4e0fa54582cd5a5d895657c32079b1ead829db/CotEditor/Sources/NSAnimationContext.swift#L31)

上記のようなAPIを実装しておくと、利用側からは以下のようにシンプルに使えます。

NSAnimationContext.current.withAnimation {
    paneSplitItem.isCollapsed.toggle()
}
GitHubで編集を提案

Discussion