【SwiftUI】スライダーで作った自作の色をカラーコードにするアプリ

[こちらの本](https://www.amazon.co.jp/SwiftUI-iPhone%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80%E3%83%8E%E3%83%BC%E3%83%88-iOS-Xcode-14%E5%AF%BE%E5%BF%9C/dp/4800713129)の第5章で作成した、
ColorSliderを応用したアプリを作ってみました。

## 要件
- Sliderを使ってR（赤）、G（緑）、B（青）を組み合わせた色を作る： *ここまでが本の内容*
- 作った色を16進数（カラーコード）に変換する: *本記事で行ったアレンジ*
　

☆☆ *ここからオマケ* ☆☆

- 出来た色をクリックすると、[ColorBaseアプリ](https://colorbase.app/ja)という色紹介サイトに飛ぶ
- 飛び先を作ったカラーコードの紹介URLに設定する

## 動き
GIFなのでカクカクですがこんな感じ
![ColorBaseApp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348975/d556ecfd-d005-ec39-7591-87879085ca9a.gif)

## サンプルコード

```swift:ColorBaseApp.swift
import SwiftUI

struct ContentView: View {
    @State var R:Double = 0.0
    @State var G:Double = 0.0
    @State var B:Double = 0.0
    @Environment(\.openURL) private var openURL
    
    var body: some View {
        let color = Color(red: R/255, green: G/255, blue: B/255)
        
        VStack(alignment: .center) {
            Button {
                        if let url = URL(string: "https://colorbase.app/ja/colors/\(color.toHex()!)") {
                            openURL(url)
                        }
                    } label: {
                        ZStack {
                            Circle()
                                .frame(width: 100, height: 100)
                                .padding()
                                .foregroundColor(color)
                        }
                    }
            Text("#\(color.toHex()!)")
            HStack {
                Circle()
                    .foregroundColor(.red)
                    .frame(width: 20, height: 20)
                Text(String(Int(R))).frame(width: 40)
                Slider(value: $R, in: 0...255).frame(width: 200)
            }
            HStack {
                Circle()
                    .foregroundColor(.green)
                    .frame(width: 20, height: 20)
                Text(String(Int(G))).frame(width: 40)
                Slider(value: $G, in: 0...255).frame(width: 200)
            }
            HStack {
                Circle()
                    .foregroundColor(.blue)
                    .frame(width: 20, height: 20)
                Text(String(Int(B))).frame(width: 40)
                Slider(value: $B, in: 0...255).frame(width: 200)
            }
        }
    }
}

#Preview {
    ContentView()
}

```

```swift:ColorExtension.swift
import SwiftUI

extension Color {
    func toHex() -> String? {
        // UIColorに変換
        let uiColor = UIColor(self)
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0

        // RGBコンポーネントを取得
        uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

        // 16進数に変換
        let r = Int(red * 256)
        let g = Int(green * 256)
        let b = Int(blue * 256)

        return String(format: "%02x%02x%02x", r, g, b)
    }
}
```

## ポイント
:::note
**POINT１: バインド変数**
Slider構造体のValueをバインド変数にし、
スライダーの動きに合わせて色や文字を動的に変化させる

```swift:SliderStruct
@State var R:Double = 0.0 // R(Red)をバインド変数で定義
@State var G:Double = 0.0 // G(Green)
@State var B:Double = 0.0 // B(Blue)

Slider(value: $R, in: 0...255) // Slider構造体のvalueに設定
Slider(value: $G, in: 0...255)
Slider(value: $B, in: 0...255)
```

```swift:CreatedColorByBindingVariables
// バインド変数をもとに変化するカラーを定義
let color = Color(red: R/255, green: G/255, blue: B/255)

// viewに反映
Circle().foregroundColor(color)
```
:::

:::note
**POINT２: 拡張メソッド**
RGBの組み合わせを16進数に変換する`toHex`を、拡張メソッドとして用意する

```swift:ColorExtension
extension Color {
    func toHex() -> String? { ... // Colorクラスを拡張してtoHexメソッドを追加
```
:::

:::note
**POINT３: UIColor**
SwiftUIで16進数表記を使うために、`UIColor`[^1]を用いてColorからRGBを取得する
詳しくは[この記事](https://appdev-room.com/swift-color-hexadecimal)を参照

```swift:toHex
func toHex() -> String? {
    // UIColorに変換
    let uiColor = UIColor(self)
    var red: CGFloat = 0
    var green: CGFloat = 0
    var blue: CGFloat = 0
    var alpha: CGFloat = 0

    // RGBコンポーネントを取得
    uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

    // 16進数に変換
    let r = Int(red * 256)
    let g = Int(green * 256)
    let b = Int(blue * 256)

    return String(format: "%02x%02x%02x", r, g, b)
}
```
:::

[^1]: SwiftUIより以前に出ていたUIKitというフレームワークが持つカラーオブジェクトクラスのこと。
[公式リファレンス：UIColor](https://developer.apple.com/documentation/uikit/uicolor)

## 感想
完全に自分だけのローカル環境で楽しむ用ですが、簡素ながら作ってみました。
自分はAndroidユーザーなのでプライベートで楽しむことは叶いませんが(泣)、
iPhoneユーザーの方はぜひ参考にしたり、アレンジしてみてください。

## 参考サイト・文献
お気に入りのカラーコード検索サイト：Colorbase

https://colorbase.app/ja

SwiftUIの入門書：詳細!SwiftUI iPhoneアプリ開発入門ノート[2022]

https://www.amazon.co.jp/SwiftUI-iPhone%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80%E3%83%8E%E3%83%BC%E3%83%88-iOS-Xcode-14%E5%AF%BE%E5%BF%9C/dp/4800713129

その他参照記事

https://appdev-room.com/swift-color-hexadecimal

https://developer.apple.com/documentation/uikit/uicolor

https://developer.apple.com/documentation/swiftui/openurlaction