LoginSignup
6
8

SwiftUIであそぼ!〜 Flip Transition 〜

Posted at

本記事について

毎日数分でも良いから、SwiftUIで遊びたいと思っていたところ、素晴らしいYouTubeチャンネルを見つけました。

このチャンネルは、SwiftUIを使った実装を多く取り上げており、新しい実装アイディアを得るのに最適です。

今回は、動画で解説されている実装を模写し、まとめたいと思います。

完成イメージ

カスタムしたTransitionのアニメーションを実装し、フリップできるViewを作成します。
こちらの動画を参考にしました!

demo_gif.gif

学べること

  • ViewModifierの使い方
  • Transitionのアニメーション

実装の解説

全体の実装

import SwiftUI

struct ContentView: View {
    @State private var showView: Bool = false

    var body: some View {
        VStack {
            ZStack {
                if showView {
                    RoundedRectangle(cornerRadius: 25)
                        .fill(.black.gradient)
                        .transition(.reverseFlip)
                } else {
                    RoundedRectangle(cornerRadius: 25)
                        .fill(.red.gradient)
                        .transition(.flip)
                }
            }
            .frame(width: 200, height: 300)
            
            Button(showView ? "Hide" : "Reveal") {
                withAnimation {
                    showView.toggle()
                }
            }
            .padding(.top, 30)
        }
    }
}

#Preview {
    ContentView()
}

struct FlipTransition: ViewModifier, Animatable {
    var progress: CGFloat = 0
    var animatableData: CGFloat {
        get { progress }
        set { progress = newValue }
    }

    func body(content: Content) -> some View {
        content
            .opacity(progress < 0 ? (-progress < 0.5 ? 1 : 0) : progress < 0.5 ? 1 : 0)
            .rotation3DEffect(
                .init(degrees: progress * 180),
                axis: (x: 0.0, y: 1.0, z: 0.0)
            )
    }
}

extension AnyTransition {
    static let flip: AnyTransition = .modifier(
        active: FlipTransition(progress: 1),
        identity: FlipTransition()
    )
    
    static let reverseFlip: AnyTransition = .modifier(
        active: FlipTransition(progress: -1),
        identity: FlipTransition()
    )
}

ViewModifierについて

ViewModifierプロトコルによって、カスタムのmodifierを再利用できるようになります。

下記のような形でカスタムのModifierを作ることができます。

struct CustomModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.caption2)
    }
}

今回の実装では、.rotation3DEffect.opacityを使ってViewをflipできるアニメーションを実現しています。

AnyTransitionの拡張

AnyTransitionは、トランジションのアニメーションを定義する型です。

下記のように定義することで、Transitionのアニメーションを新たに追加することができます。

// 定義
static let custom: AnyTransition = .modifier(active: CustomTransition(value: 1), identity: CustomTransition())

// 利用側
RoundedRectangle(cornerRadius: 25).transition(.custom)

終わりに

今度は別の動画の実装を模写し、SwiftUIの表現力を強化したいです。

6
8
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
6
8