見出し画像

SwiftUIでいこう! - WWDC23 - Custum Animation

Custum Animation

前回の続きです。アニメーションの構造体を作り動きを"func"関数を作ります。CustomAnimationプロトコルを使って作ります。

struct MyAnimation:CustomAnimation{
    var duration:CGFloat = 1
    func animate<V>(value: V, time: TimeInterval, context: inout AnimationContext<V>) -> V? where V : VectorArithmetic {
        if time > duration{return nil}
        return value.scaled(by: easeOutBounce(time / duration))
    }
    
    func easeOutBounce(_ x: TimeInterval) -> CGFloat{
        let n1 = 7.5625
        let d1 = 2.75
        var x: TimeInterval = x
        
        if (x < 1 / d1){
            return n1 * x * x
        }else if(x < 2 / d1){
            x -= 1.5 / d1
            return n1 * x * x + 0.75
        }else if(x < 2.5 / d1){
            x -= 2.25 / d1
            return n1 * x * x + 0.9375
        }else {
            x -= 2.625 / d1
            return n1 * x * x + 0.984375
        }
    }
}

ボタンにアニメーションを追加しています。

   Button("show View"){
            withAnimation(.init(MyAnimation())){
                showView.toggle()
            }
        }

これでボタンを押すと"MyAnimation()"が実行されます。

Animation Complete Callback

struct ContentView: View {
    @State private var showView:Bool = false
    var body: some View {
        VStack {
            if showView {
                Text("Hello")
            }
            
            Button("Show View"){
                withAnimation(.bouncy,completionCriteria:.removed){
                    showView.toggle()
                }completion: {
                    print("Complete But View Remove")
                }
            }
        }
        
    }
}

アニメーションが終わった後の設定です。この場合は最後に"Complete But View Remove"と出力されます。

completionCriteria:.removed

これをつけることで完全に終わらせることができる。

Update onChange Modifier

struct ContentView: View {
    @State private var value:CGFloat = 0
    var body: some View {
        VStack {
            Button("Show View"){
                value = 10
            }
        }
        .onChange(of: value, initial: true){oldValue,newValue in      
            print(oldValue,newValue)
        }
    }
}

.onChange(of: value, initial: true){oldValue,newValue in
  print(oldValue,newValue)

@Stateのついた変数の変化を感知して実行されます。

@Observable & Bindable

import SwiftUI
import SwiftData

struct ContentView: View {
    @State private var value:CGFloat = 0
    @Bindable var user:User = .init()
    var body: some View {
        VStack {
            Button("Show View"){
                value = 10
            }
        }
        .onChange(of: value, initial: true){oldValue,newValue in 
            print(oldValue,newValue)
        }
    }
}

#Preview {
    ContentView()
}

@Observable
class User{
    var name:String = ""
    var email:String = ""
}

@Observableを使ってモデルを使う。@Bindableでモデルを".init()"することで実行しているようです。

@Bindable var user:User = .init()

Creates a bindable object from an observable object.

UnEvenRoundedRectangle

struct ContentView: View {
    var body: some View {
      UnevenRoundedRectangle(topLeadingRadius: 35,bottomLeadingRadius: 35)
            .fill(.red.gradient)
            .frame(width: 200,height: 200)
    }
}

以下でも同じことができます。

struct ContentView: View {
    var body: some View {
          Rectangle()
            .fill(.red.gradient)
            .frame(width: 200,height: 200)
            .clipShape(.rect(topLeadingRadius: 35))
    }
}


Hepatics FeedBack

struct ContentView: View {
    @State private var feedback:Bool = false
    var body: some View {
        Button("Send Haptic Feedback"){
            feedback.toggle()
        }
        .sensoryFeedback(.warning, trigger: feedback)
    }
}ss

いろんな状態を取得して返すことができます。

この記事が気に入ったらサポートをしてみませんか?