Last active
November 5, 2022 09:59
-
-
Save HonmaMasaru/5d00ead8fce849327defae8371b7eb53 to your computer and use it in GitHub Desktop.
ColorConverter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import RegexBuilder | |
import PlaygroundSupport | |
enum ColorCode { | |
/// 6文字および8文字のカラーコードの正規表現 | |
/// /^#?([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})?$/ | |
private static let hexCapture = Capture { Repeat(count: 2) { .hexDigit } } | |
private static let pattern8 = Regex { | |
Optionally { "#" } | |
hexCapture // R | |
hexCapture // G | |
hexCapture // B | |
Optionally { hexCapture } // A | |
} | |
/// 3文字のカラーコードの正規表現 | |
/// /^#?([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/ | |
private static let pattern3 = Regex { | |
Optionally { "#" } | |
Capture { .hexDigit } // R | |
Capture { .hexDigit } // G | |
Capture { .hexDigit } // B | |
} | |
/// カラーコードをRGB値に変換 | |
/// - Parameter hexStr: カラーコード | |
/// - Returns: RGB値 | |
static func convert(from hexStr: String) -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat)? { | |
// 6文字および8文字 | |
if let match = hexStr.wholeMatch(of: pattern8) { | |
let (_, r, g, b, a) = match.output | |
return (toDecimal(r), toDecimal(g), toDecimal(b), toDecimal(a ?? "ff")) | |
} | |
// 3文字 | |
if let match = hexStr.wholeMatch(of: pattern3) { | |
let (_, r, g, b) = match.output | |
return (toDecimal(r), toDecimal(g), toDecimal(b), 1.0) | |
} | |
return nil | |
} | |
/// 16進をカラー値に変換 | |
/// - Parameter hex: 16進 (文字列) | |
/// - Returns: カラー値 | |
private static func toDecimal(_ hex: Substring) -> CGFloat { | |
let h: String = hex.count == 1 ? .init(repeating: .init(hex), count: 2) : .init(hex) | |
return .init(Int(h, radix: 16) ?? 0) / 255.0 | |
} | |
} | |
struct ColorConverter: View { | |
/// カラーコード入力 | |
@State private var colorCode: String = "" | |
/// UIColorの出力 | |
@State private var uiColorString: String = "" | |
/// Colorの出力 | |
@State private var colorString: String = "" | |
/// パレットのカラー | |
@State private var color: Color? | |
/// body | |
var body: some View { | |
HStack { | |
RoundedRectangle(cornerRadius: 8) | |
.fill(color ?? .black) | |
.frame(width: 80, height: 80) | |
VStack { | |
TextField("カラーコード", text: $colorCode) | |
.textFieldStyle(RoundedBorderTextFieldStyle()) | |
TextField("UIColor", text: .constant(uiColorString), axis: .vertical) | |
.textSelection(.enabled) | |
.font(.caption) | |
.frame(maxHeight: .infinity) | |
TextField("Color", text: .constant(colorString), axis: .vertical) | |
.textSelection(.enabled) | |
.font(.caption) | |
.frame(maxHeight: .infinity) | |
} | |
} | |
.frame(width: 400, height: 150) | |
.padding() | |
.onChange(of: colorCode, perform: convert) | |
} | |
/// 出力 | |
private func convert(_ colorCode: String) { | |
if let c = ColorCode.convert(from: colorCode) { | |
uiColorString = "UIColor(red: \(c.r), green: \(c.g), blue: \(c.b), alpha: \(c.a))" | |
colorString = "Color(red: \(c.r), green: \(c.g), blue: \(c.b), opacity: \(c.a))" | |
color = .init(red: c.r, green: c.g, blue: c.b, opacity: c.a) | |
} else { | |
uiColorString = "" | |
colorString = "" | |
color = nil | |
} | |
} | |
} | |
PlaygroundPage.current.setLiveView(ColorConverter()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment