見出し画像

SwiftUIでいこう! - Animation Timer! 2

画面上で初期画面、ボタンを押すとアニメーションして画面の色を変え、押したボタンの数字を表示することができるようになりました。

画像1

続いて、タイマーの実装をやっていきます。ボタンを押すことでカウントダウンしていきます。

ZStack{}にかかる制御の命令を書いていきます。

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

この下に

 .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect(), perform: { _ in
           if data.time != 0 && data.selectedTime != 0{
               data.selectedTime -= 1
           }
  })

として、Timer実装します。これで、変数Time,selectedTimeに0以外の数字が入ったら

data.selectedTime -= 1

を実行します。これがTimer.publish()で定義されているように、1秒ごとに動きます。なので、1秒ごとに、変数"data.selectedTime"に入っている数字を"1"引いていきます。

TimerData()は最終的には以下となります。

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
   @Published var timerHeightChange:CGFloat = 0
   
}

変数"timeViewOffset"で画面の高さを取得します。

変数"timerHeightChange"でタイマーが始まったと同時に画面を覆っているピンクの画面の高さを変えるために使います。

.onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect(), perform: { _ in
           if data.time != 0 && data.selectedTime != 0 && data.buttonAnimation{
               data.selectedTime -= 1
               
               let ProgressHeight = UIScreen.main.bounds.height / CGFloat(data.time)
               let diff = data.time - data.selectedTime
               withAnimation(.default){
                   data.timerHeightChange = CGFloat(diff) * ProgressHeight
               }
               if data.selectedTime == 0{
                   withAnimation(.default){
                       data.time = 0
                       data.selectedTime = 0
                       data.timerHeightChange = 0
                       data.timeViewOffset = UIScreen.main.bounds.height
                       data.buttonAnimation = false
                   }
               }
               
           }
       })


タイマースタートと同時に

let ProgressHeight = UIScreen.main.bounds.height / CGFloat(data.time)
let diff = data.time - data.selectedTime
withAnimation(.default){
     data.timerHeightChange = CGFloat(diff) * ProgressHeight
 }
 if data.selectedTime == 0{
     withAnimation(.default){
     data.time = 0
     data.selectedTime = 0
     data.timerHeightChange = 0
     data.timeViewOffset = UIScreen.main.bounds.height
     data.buttonAnimation = false
      }
 }

とします。

let ProgressHeight = UIScreen.main.bounds.height / CGFloat(data.time)

画面の高さを時間によって変化させる計算をしたものを変数に入れます。

let diff = data.time - data.selectedTime

経過時間を取得して、

withAnimation(.default){
 data.timerHeightChange = CGFloat(diff) * ProgressHeight
}

アニメーション、ピンク画面をだんだん小さくしていき、最後"0"の時にピンク画面も無くなります。この変数は

ZStack {
  VStack{}
  Color.pink

Color.pinkで画面を覆う色をつける命令で適応されます。

Color.pink
      .overlay(
         Text("\(data.selectedTime)")
            .font(.system(size: 55,weight:.heavy))
            .foregroundColor(.white)
       )
      .frame(height:UIScreen.main.bounds.height - data.timerHeightChange)
      .frame(maxWidth:.infinity,maxHeight:.infinity,alignment: .bottom)
      .ignoresSafeArea(.all,edges: .all)
      .offset(y:data.timeViewOffset)

.overlayを一番上に持っていき、

.frame(height:UIScreen.main.bounds.height - data.timerHeightChange)

でピンク色で覆った画面が時間によって高さが変わるようになります。時間を表示する数字も一緒に変化していきます。

if data.selectedTime == 0{}

これで、タイマーが"0"になった時の変数をリセットします。

data.time = 0
data.selectedTime = 0
data.timerHeightChange = 0
data.timeViewOffset = UIScreen.main.bounds.height
data.buttonAnimation = false

これで一通り数字を選び、スタートボタンでスタート、カウントダウン、終了後にリセットされるようになりました。


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