LoginSignup
3
2

はじめに

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

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

要件

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

準備

プロジェクトの作成方法は、Swift & SwiftUIでタロットカードアプリを作る を参照してください。

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

今回のディレクトリ構成

ContentViewのみ修正してます。

実装

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に変換しました。

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

まとめ

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

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

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

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2