LoginSignup
0
2

More than 1 year has passed since last update.

Pathの形状をアニメーションで変更する (SwiftUI)

Last updated at Posted at 2023-03-26

SwiftUIはアニメーション関連の機能が充実しており、animation(_:value:)withAnimation(::)などで、簡単にUIのインタラクションを実現できます。

自分が思いつく限りのインタラクションは大体それらで事足ります。

ただ最近、他のアプリでちょっと面白い動きをするUIを見かけ、どうやっているんだろうと考えているうちに、拡大・縮小などanimationでいじれる範囲のプロパティーではその動きは実現できそうにない、という結論に達しました。

UIの形状自体を変える必要がありそうです。

そのアプリはおそらくSwiftUIでなく、Unityとかその辺りを使っていると思われますが、自分はその辺に疎いのでSwiftUIでなんとか実現したいと思いました。

その下準備として、SwiftUIで「Pathのポイントをアニメーションで移動させて形状を変える」というのを試してみることにします。

具体的にはこういった感じです。

画面収録 2023-03-26 16.00.58.gif

円(正確には30角形)と矩形をアニメーションで遷移させています。

ソースに関してはこちらで、Playgroundにコピペで実行できます。


普段はanimationとかを追加するだけなので、アニメーションがどう実行されているかに関しては気にしたことがなかったのですが、今回初めて触れることができました。

アニメーションを自前で実装する際はanimatableDataというプロパティが肝になるようです。

L10-

    /// アニメーション対象
    var animatableData: AnimatableCGPointVector {
        get { points }
        set { points = newValue }
    }

こちらはAnimatableプロトコルで指定されており、適合することで設定したプロパティがアニメーションに対応します。

ShapeAnimatable含んでいるので、そのままanimatableDataを設定することができます。

animatableDataに指定するプロパティはどんな型でも良いわけではなく、VectorArithmeticプロトコルに適合した型である必要があります。

もっと正確にいうと、指定自体はどんな型でもできるみたいですが、VectorArithmeticに適合した型でないとアニメーションは実行されません。

VectorArithmeticは、加減算を行うプロトコルであるAdditiveArithmeticを拡張したものであり、アニメーションの始点と終点の間の数値を補完する目的で使われているようです。


さてここで問題が生じます。

Pathを描画するためのCGPointですが、配列で利用する必要があります。

L16-

    /// パスの作成
    /// - Parameter rect: 領域
    /// - Returns: パス
    func path(in rect: CGRect) -> Path {
        .init { $0.addLines(points.values) }
    }

CGPoint自体はAnimatable適合しているのですが、Array<CGPoint>Animatableに適合していません。(Array自体が適合していない) 1

そこでArray<CGPoint>Animatableに適合させようと色々調べているうちに、その用途に使えるコードがgistで見つかりましたので、今回はそのコードをそのまま使わせてもらいました。

The type that holds array of CGPoints and conforms to VectorArithmetic

こちらのソースもアニメーションがどう動くかの参考になります。


ここまで書いてなんですが、アニメーションの概念自体はこちらのページで詳しく解説されておりますのでご参照ください。

SwiftUI で Animatable なシェイプを作ってみる - Qiita

AnimatableShapeの部分は円や矩形に限らず、ポイントを渡せばアニメーションにできる感じになっていますので色々使い回せそうです。

ここに曲線とかが絡んでくるとまためんどくさくなりそうですが、とりあえず勘所は掴めたのでよかったです。

ソースコード

  1. Animatableに適合しているのでanimatableDataを利用できる。AnimatableDataはassociatedtypeとしてVectorArithmetic設定されている

0
2
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
0
2