見出し画像

SwiftUIでいこう! - 時計を作る。

WWDC20を追いかけていますが、今回は今のSwiftUIです。

時計のアナログ時計の作り方を紹介されているのを見つけたので、ちょっとやってみます。

まずは時間を取得しないといけません。

@State var hour = Calendar.current.component(.hour, from: Date())

これで、今の時間が変数"hour"に入っていきます。

struct ContentView: View {
   
   @State var hour = Calendar.current.component(.hour, from: Date())
   
   var body: some View {
       Text("今の時間は \(hour)")
   }
}

として表示させてみると、" \(hour)"のところに今の時間が表示されます。分と秒も追加しましょう。

@State var minute = Calendar.current.component(.minute, from: Date())
@State var second = Calendar.current.component(.second, from: Date())

これで時間は取得できたので、次に時計の針を作っていきます。これはpath(パス)を書いて動かします。

その前にスクリーンサイズを取得しておきます。

var screenWidth = UIScreen.main.bounds.width
var screenHeight = UIScreen.main.bounds.height

そして、時計の針をPathで作っていきます。

struct ClockHands:View {
 var body: some View {
   Path{path in
       path.move(to: CGPoint(x: screenWidth/2, y: screenHeight/2))
       path.addLine(to:CGPoint(x: screenWidth/2, y: screenHeight/2 - (screenWidth * 2/5)))
   }.stroke()
 }
}
path.move(to: CGPoint(x: screenWidth/2, y: screenHeight/2))

でまず開始点を移動しておいて、

path.addLine(to:CGPoint(x: screenWidth/2, y: screenHeight/2 - (screenWidth * 2/5)))

で上むきに向けて、.stroke()で線をひきます。線に色と太さを決めてやります。

まず変数を作って、

 @State var color:UIColor
 @State var lineWidth:CGFloat

.stroke()に線の色と太さを指定できるようにします。

.stroke(Color(color),lineWidth: lineWidth)

ContentViewの中に、時計の針3本"ClockHands()"を入れます。この時ですが針は重なって動くので、重なりの時に使うZStack {}を使います。

struct ContentView: View {
   
   @State var hour = Calendar.current.component(.hour, from: Date())
   @State var minute = Calendar.current.component(.minute, from: Date())
   @State var second = Calendar.current.component(.second, from: Date())
   
   
   var body: some View {
       ZStack {
           ClockHands(color: .black, lineWidth: 4)
           ClockHands(color: .black, lineWidth: 4)
           ClockHands(color: .red, lineWidth: 4)
       }
   }
}

あとは時計の針に動きをつけていきます。時、分、秒の"時"からです。

ClockHands(color: .black, lineWidth: 4).scaleEffect(0.7).rotationEffect(.degrees(Double(hour * 30 + minute * Int(0.5))))
rotationEffect(.degrees(Double(hour * 30 + minute * Int(0.5))))

で回転の動きです。".degrees"が角度です。時計は1周、12時間。角度は360度なので360/12= 30。minute * Int(0.5)は1分立つたびに0.5度回していきます。同じように、分、秒についても計算して動かします。

ClockHands(color: .black, lineWidth: 4).rotationEffect(.degrees(Double(minute * 6)))
ClockHands(color: .red, lineWidth: 2).scaleEffect(0.8).rotationEffect(.degrees(Double(second * 6)))

これで、時計のはりが動く仕組みができました。あとは時間通りに動いてくれれば良いことになります。この時間通りに動かす仕組みを作ります。

let timer = Timer.publish(every: 1, on: .current, in: .common).autoconnect()

Timer()を作ります。1秒ごとに進んで行きます。このタイマーを使うタイミングは、 ZStack{}の直下、すぐあと、

 ZStack {
  // 時計の針を作る
}.onReceive(timer){ _ in
           self.hour = Calendar.current.component(.hour, from: Date())
           self.minute = Calendar.current.component(.minute, from: Date())
           self.second = Calendar.current.component(.second, from: Date())
       }
.onReceive(timer){  _ in
//  処理
}

これでタイマーを動かすことができます。1秒ごとに

self.hour = Calendar.current.component(.hour, from: Date())
self.minute = Calendar.current.component(.minute, from: Date())
self.second = Calendar.current.component(.second, from: Date())

を行います。hour,minute,secondsに現在の時間を取り込んで行きます。

この取得した時間で時計の針を動かします。

画像1

時計が動くようになりました。




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