SwiftUI 表と裏を切り替えてカードめくりを表現する


はじめに

ちょっと便利なものを作ってみました。カードゲームを作ったり、面白いUIをアプリに組み込みたいときにどうぞ。

使い方

表: true, 裏: false

  • @State var isFront = true みたいな感じで、 表裏の状態を表す変数 を作っておいてください。 ボタンを押した時とかにこの変数を変更すれば 表裏が切り替わります。

Flip

  • Flip(変数, { 表 }, { 裏 }) を使います。
  • duration: めくるスピードを調整できます。設定しなくてもOK。
Sample.swift

...
// 裏と表がある View
Flip(isFront: isFront, // 先に作っておいた変数 isFront
     front: {

         Image("H1") // 表面 ハートのA
     },
     back: {

         Image("Back") // カード裏面
     })
...

コピペ用コード

丸々コピペしてプロジェクト内のどこかにおいてください。

Flip.swift

import SwiftUI

struct Flip<Front: View, Back: View>: View {
    var isFront: Bool
    @State var canShowFrontView: Bool
    let duration: Double
    let front: () -> Front
    let back: () -> Back

    init(isFront: Bool,
         duration: Double = 1.0,
         @ViewBuilder front: @escaping () -> Front,
         @ViewBuilder back: @escaping () -> Back) {
        self.isFront = isFront
        self._canShowFrontView = State(initialValue: isFront)
        self.duration = duration
        self.front = front
        self.back = back
    }

    var body: some View {
        ZStack {
            if self.canShowFrontView {
                front()
            }
            else {
                back()
                    .rotation3DEffect(Angle(degrees: 180), axis: (x: 0, y: 1, z: 0))
            }
        }
        .onChange(of: isFront, perform: {
            value in
            DispatchQueue.main.asyncAfter(deadline: .now() + duration/2.0) {
                self.canShowFrontView = value
            }
        })
        .animation(nil)
        .rotation3DEffect(isFront ? Angle(degrees: 0): Angle(degrees: 180), axis: (x: CGFloat(0), y: CGFloat(10), z: CGFloat(0)))
        .animation(.easeInOut(duration: duration))
    }
}

さいごに

「めくる」って何か良い響きですよね