SwiftとSwiftUIでイラっとするデジタル時計を作る

# はじめに
こんにちは！
最近、改めてSwiftはできた方がいいな、と思い、少しずつ学習中です。

今回は、デジタル時計を作ります。
せっかくなので、色々な効果を適用して、イラっとする動きにしてみました。

# 要件
- デジタル時計を表示する
- 1秒おきに様々な効果を適用する

# 準備
プロジェクトの作成方法は、[Swift & SwiftUIでタロットカードアプリを作る](https://qiita.com/yam_dev/items/871b47c1065f570ff17a) を参照してください。

User Interfaceは`SwiftUI`を選択しました。

### 今回のディレクトリ構成
ContentViewのみ修正してます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/84e1fde8-867f-7f38-411a-649e7dbc71e6.png" width="60%" />

# 実装
```swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    // 時間を「HH:mm:ss」の形式にフォーマットするためのDateFormatterを定義
    let timeFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm:ss"
        return formatter
    }()

    // 現在時刻を保持する状態変数
    // @State属性により、値が変更されるとViewが再描画される
    @State private var currentTime: String = ""
    // 適用するエフェクトの種類を決定する状態変数
    @State private var effectIndex: Int = 0

    var body: some View {
        VStack { // 要素を縦方向に配置するVStackビュー
            Text(currentTime) // 現在時刻を表示するTextビュー
                .font(.system(size: 50, weight: .bold, design: .monospaced)) // フォントの設定
                .foregroundColor(.white) // 文字色の設定
                .lineLimit(1) // 最大行数を1行に制限
                .padding() // 余白の追加
                .onAppear { // Viewが表示されたときに実行される処理
                    // 1秒ごとにタイマーを実行し、現在時刻を更新してエフェクトの種類をランダムに変更する
                    Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
                        currentTime = timeFormatter.string(from: Date())
                        effectIndex = Int.random(in: 0...3)
                    }
                }
                .modifier(DistortionEffect(effectIndex: effectIndex)) // DistortionEffectモディファイアを適用
        }
        .background(Color.black) // 背景色の設定
    }
}

// Viewにエフェクトを追加するための構造体
struct DistortionEffect: ViewModifier {
    // エフェクトの種類を指定する変数
    let effectIndex: Int

    // モディファイアを適用した結果のViewを返す
    func body(content: Content) -> some View {
        Group {
            // effectIndexの値に応じて適用するエフェクトを変更する
            switch effectIndex {
            case 0:
                // 何もしない
                content
            case 1:
                // 歪みエフェクト
                content.projectionEffect(.init(CGAffineTransform(a: 1, b: CGFloat.random(in: -0.1...0.1), c: CGFloat.random(in: -0.1...0.1), d: 1, tx: 0, ty: 0)))
            case 2:
                // サイズエフェクト
                content
                    .scaleEffect(CGFloat.random(in: 0.95...1.05)) // Viewのサイズを変更するscaleEffectモディファイアを適用
            case 3:
                // 透過度エフェクト
                content
                    .opacity(Double.random(in: 0.5...1)) // Viewの透過度を変更するopacityモディファイアを適用
            default:
                // 上記以外の場合は何もしない
                content
            }
        }
    }
}

// プレビュー用の構造体
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```
# 動作確認
それでは、使ってみましょう！

シミュレーターで起動すると、すぐにデジタル時計が動き出します。
今回は録画したものをGIFに変換しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/931ffb15-341d-7784-f0fc-4cff58f99f85.gif" width="200" />

斜めになると、ちょっとイラッとしますねw
ある意味ストレス発散になるかも。

# まとめ
今回は、コンテンツに動きをつける目的で、デジタル時計を作ってみました。

様々な効果を適用できるので、みなさんも試してみてくださいね。

アプリの可能性は無限にあるので、一緒にチャレンジしましょう🙂