Skip to content

Instantly share code, notes, and snippets.

@HonmaMasaru
Last active November 5, 2022 09:59
Show Gist options
  • Save HonmaMasaru/5d00ead8fce849327defae8371b7eb53 to your computer and use it in GitHub Desktop.
Save HonmaMasaru/5d00ead8fce849327defae8371b7eb53 to your computer and use it in GitHub Desktop.
ColorConverter.swift
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