SwiftUI入門-勉強メモ016- 【アニメーションその1】

SwiftUI


今回はAnimation(アニメーション)です.

環境は,

  • macOS Catalina 10.15.7
  • Xcode 12.0.1
  • Swift 5.3
  • iOS 14.0

です.

目次

Animationとは

Viewの形状やエフェクトをアニメーションにすることができます.

これは具体的に見たほうが早いかもしれません.

基本的なアニメーション

基本的な方法はViewを.animationで修飾することです.

簡単な例を見てみます. ボタンを押すごとに円が大きくなったり, 小さくなったりします.

import SwiftUI

struct ContentView: View {
    
    @State private var scale: CGFloat = 1
    
    var body: some View {
        VStack (spacing: 200) {
            Stepper(value: $scale, in:1...5, step: 0.5) {
                Text("倍率: \(scale, specifier: "%.1f")倍")
            }
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.default)
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
SwiftUI
SwiftUI

上の例で見たような形を変える際のアニメーションは, いくつか用意されています.

種類説明
defaultデフォルト設定
linear一定の割合で変化します
easeIn変化の速度が遅い→早いとなります
easeOut変化の速度が早い→遅いとなります
easeInOut変化の速度が遅い→早い→遅いとなります
linearメソッド
static func linear(duration: Double) -> Animation
  • duration:アニメーションの動作時間を指定します

これも実例を見たほうが早いかもしれません.

import SwiftUI

struct ContentView: View {
    
    @State private var scale: CGFloat = 1
    
    var body: some View {
        VStack (spacing: 100) {
            Stepper(value: $scale, in: 1...3, step: 2) {
                Text("Scale \(scale, specifier: "%.1f")")
            }
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.linear(duration: 5.0))
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.easeIn(duration: 5.0))
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.easeOut(duration: 5.0))
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.easeInOut(duration: 5.0))
        }
        .padding()
    }
}

上から順に, linear, easeIn, easeOut, easeInOutです. 少し違いがあるのがわかるでしょうか.

弾力のあるアニメーション

弾力のあるアニメーションの基本

これも何種類か存在します.

種類説明
interactiveSpringインタラクティブなバネのアニメーションを表示させます
interpolatingSpring補間スプリングのアニメーションを表示させます
springバネのアニメーションを表示させます
interactiveSpringメソッド
static func interactiveSpring(response: Double = 0.15, dampingFraction: Double = 0.86, blendDuration: Double = 0.25) -> Animation
  • response:バネの剛性を示す接続時間
  • dampingFraction:バネの特性を示す減衰率
  • blendDuration:バネの応答値に対する変更を補間する時間を指定します
interpolatingSpringメソッド
static func interpolatingSpring(mass: Double = 1.0, stiffness: Double, damping: Double, initialVelocity: Double = 0.0) -> Animation
  • mass:バネに取りつけられた重りの質量
  • stiffness:バネの弾力
  • damping:バネの減衰値
  • initialVelocity:バネの初期速度を0〜1の範囲で指定します
springメソッド
static func spring(response: Double = 0.55, dampingFraction: Double = 0.825, blendDuration: Double = 0) -> Animation
  • response:バネの剛性を示す接続時間
  • dampingFraction:バネの特性を示す減衰率
  • blendDuration:バネの応答値に対する変更を補間する時間を指定します

うーん. まったくわかりません. 簡単なコードをかいてみました.

import SwiftUI

struct ContentView: View {
    
    @State private var scale: CGFloat = 1
    
    var body: some View {
        VStack (spacing: 100) {
            Stepper(value: $scale, in: 1...3, step: 1) {
                Text("Scale \(scale, specifier: "%.1f")")
            }
            Circle()
                .fill(Color.pink)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.interpolatingSpring(
                            stiffness: 10, damping: 1))
            Circle()
                .fill(Color.blue)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.spring())
            Circle()
                .fill(Color.green)
                .frame(width: 50, height: 50)
                .scaleEffect(scale)
                .animation(.interactiveSpring())
        }
        .padding()
    }
}

何となく違いがわからなくもないですね. 値によってどう変化するのか, springで見てみることにしました.

import SwiftUI

struct ContentView: View {
    
    @State private var scale: CGFloat = 1
    @State private var response = 0.55
    @State private var dampingFraction = 0.86
    @State private var blendDuration = 0.25
    
    var body: some View {
        VStack {
            Stepper(value: $scale, in: 1...8, step: 1) {
                Text("Scale \(scale, specifier: "%.1f")")
            }
            Spacer()
            Circle()
                .fill(Color.pink)
                .frame(width: 35, height: 35)
                .scaleEffect(scale)
                .animation(
                    .spring(
                        response: response,
                        dampingFraction: dampingFraction,
                        blendDuration: blendDuration
                    )
                )
            Spacer()
            HStack{
                Text("response:\(response, specifier: "%.2f")")
                Slider(value: $response, in: 0...1)
            }
            HStack{
                Text("dampingFraction:\(dampingFraction, specifier: "%.2f")")
                Slider(value: $dampingFraction, in: 0...1)
            }
            HStack{
                Text("blendDuration:\(blendDuration, specifier: "%.2f")")
                Slider(value: $blendDuration, in: 0...1)
            }
        }
        .padding()
    }
}
SwiftUI

ボタンを押すたびに回転するアニメーション

import SwiftUI

struct ContentView: View {
    @State private var angle: Double = 0
    var body: some View {
        VStack {
            Spacer()
            Button(action: { self.angle += 30 }) {
                Text("30°回転させる")
                    .foregroundColor(.blue)
                    .font(.largeTitle)
            }
            Spacer()
            Image(systemName:"hare.fill")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 200)
                .foregroundColor(Color.pink)
                .rotationEffect(.degrees(angle))
                .animation(.spring())
            Spacer()
        }
    }
}
SwiftUI
SwiftUI
よかったらシェアしてね!

コメント

コメントする

目次
閉じる