見出し画像

SwiftUIでいこう! - Animation Timer! 1

ちょっと変わったアニメーションを使ったタイマーです。参考サイトをみながら組み上げていきます。

Xcode、プロジェクトを作って、最初からContentViewはありますが、別viewとしてHomeView.swiftという名前でSwiftUIファイルを作ってまず表示画面を作っていきます。

骨組みは以下のようになります。

 var body: some View {
       VStack{
           Spacer()
           ScrollView(.horizontal,showsIndicators:false,content:{
               
               HStack(spacing:20){
                   ForEach(1...6,id:\.self){index in
                       let time = index * 5
                       Text("\(time)")
                   }
               }
               .padding()
           })
           Spacer()
       }
   }

Spacer()を使って表示部分を中央へ持っていきます。

HStack、ForEachで横並びに数字を並べます。その時円形に形を整え色をつけます。

 Text("\(time)")
     .font(.system(size: 30,weight:.heavy))
     .frame(width:80,height: 80)
     .background(Color.blue)
     .foregroundColor(.white)
     .clipShape(Circle())

こんな感になります

画像1

次にデータを入れるモデルを作ります。TimerViewModelという名前でswiftファイルを作ります。

import SwiftUI

class TimerData:ObservableObject{
   
   @Published var time:Int = 0
   @Published var selectedTime:Int = 0
   @Published var buttonAnimation = false
   @Published var timeViewOffset:CGFloat = UIScreen.main.bounds.height
}

ObservableObjectに適合したクラスを作ります。

@Published var time:Int = 0
@Published var selectedTime:Int = 0

これはボタンを選択した時に使う変数。

@Published var buttonAnimation = false

これはアニメーションを動かす時に使う変数。

@Published var timeViewOffset:CGFloat = UIScreen.main.bounds.height

これはアニメーションする時の画面変化に使う変数となっています。

HomeViewを編集していきます。別ファイルで作ったクラスを使えるように変数に代入します。

@StateObject var data = TimerData()

青丸の数字をタップした時の動きを書いていきます。

Text("\(time)")
  ......................
     .background(data.time == time ? Color.pink : Color.blue)
  ......................
    .onTapGesture {
     data.time = time
     data.selectedTime = time
     }

タップした時に

data.time = time
data.selectedTime = time

とするので、タップすると、 data.time = timeとなるので、

.background(data.time == time ? Color.pink : Color.blue)

の動きで丸文字はピンクとなります。

次にアニメーション、タイマーを動かすボタンを作っていきます。まずはアニメーションをつけていきます。

Button(action: {
                   withAnimation(Animation.easeInOut(duration:0.65)){
                       data.buttonAnimation.toggle()
                   
                   }
                   withAnimation(Animation.easeIn.delay(0.6)){
                       data.timeViewOffset = 0
                   }
                   
               }
               , label: {
                   Circle()
                       .fill(Color.pink)
                       .frame(width:90,height:90)
               })
               .padding(.bottom,35)
               .disabled(data.time == 0)
               .opacity(data.time == 0 ? 0.6: 1)
               .offset(y:data.buttonAnimation ? 300:0)
               
               
           }

表示部分は

label: {
  Circle()
  .fill(Color.pink)
  .frame(width:90,height:90)
}

ピンクのまるです。

.padding(.bottom,35)
.disabled(data.time == 0)
.opacity(data.time == 0 ? 0.6: 1)
.offset(y:data.buttonAnimation ? 300:0)

の部分で初期状態変数の値が変化した場合の制御を行います。

これを押すと、変数の値を変化させてアニメーションをスタートします。

withAnimation(Animation.easeInOut(duration:0.65)){
  data.buttonAnimation.toggle()

}
withAnimation(Animation.easeIn.delay(0.6)){
  data.timeViewOffset = 0
}

あとはVStackと並列にColorを設置。

Color.pink
   .ignoresSafeArea(.all,edges: .all)
   .overlay(
       Text("\(data.selectedTime)")
         .font(.system(size: 55,weight:.heavy))
         .foregroundColor(.white)
          )
         .offset(y:data.timeViewOffset)

VStackとColorの上位にZStackをつけます。画面上を色を被せる形をとります。

.offset(y:data.timeViewOffset)

で制御します。あとはZStackを以下で前面黒くしています。

.frame(maxWidth: .infinity,maxHeight: .infinity)
.background(Color(.black).ignoresSafeArea(.all,edges: .all))

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