web-dev-qa-db-ja.com

Color SwiftUIからRGBコンポーネントを取得する方法

SwiftUIがある場合Color

let col: Color = Color(red: 0.5, green: 0.5, blue: 0.5)

colからRGBコンポーネントを取得するにはどうすればよいですか?
多分これのように:

print(col.components.red)

UIKitでは、UIColor.getRedですが、SwiftUIには同等のものがないようです。

10
Div

答えはnoですまだ)APIはありませんが...

ほとんどのSwiftUI構造体には、privateのようなColorのフィールドがあります。

Mirrorを使用してそのような情報を抽出できますが、効率的ではないことに注意してください。

教育目的でSwiftUI Colorの16進数表現を抽出する方法は次のとおりです。

これをコピーして---(Xcode 11プレイグラウンドに貼り付けます。

import UIKit
import SwiftUI

let systemColor = Color.red
let color = Color(red: 0.3, green: 0.5, blue: 1)

extension Color {

    var hexRepresentation: String? {
        let children = Mirror(reflecting: color).children
        let _provider = children.filter { $0.label == "provider" }.first
        guard let provider = _provider?.value else {
            return nil
        }
        let providerChildren = Mirror(reflecting: provider).children
        let _base = providerChildren.filter { $0.label == "base" }.first
        guard let base = _base?.value else {
            return nil
        }
        var baseValue: String = ""
        dump(base, to: &baseValue)
        guard let firstLine = baseValue.split(separator: "\n").first,
              let hexString = firstLine.split(separator: " ")[1] as Substring? else {
            return nil
        }
        return hexString.trimmingCharacters(in: .newlines)
    }

}

systemColor.hexRepresentation
color.hexRepresentation

dumpedの場合、.red.whiteなどの色には多くの情報が含まれていないようです。

それらの「システム」名だけです。

▿ red
  ▿ provider: SwiftUI.(unknown context at $1297483bc).ColorBox<SwiftUI.SystemColorType> #0
    - super: SwiftUI.(unknown context at $129748300).AnyColorBox
    - base: SwiftUI.SystemColorType.red

Color/red/blueコンポーネントでインスタンス化されたgreenは代わりに使用します。

▿ #4C80FFFF
  ▿ provider: SwiftUI.(unknown context at $11cd2e3bc).ColorBox<SwiftUI.Color._Resolved> #0
    - super: SwiftUI.(unknown context at $11cd2e300).AnyColorBox
    ▿ base: #4C80FFFF
      - linearRed: 0.073238954
      - linearGreen: 0.21404114
      - linearBlue: 1.0
      - opacity: 1.0

プレイグラウンドには、次のものが表示されます。

  • systemColor.hexRepresentation戻り値nil
  • color.hexRepresentation戻り値"#4C80FFFF"
2
Matteo Pacini

色の説明の形式が#rrggbbaaである単純なrgbaケースでCustomStringConvertibleプロトコルを乱用したAPIを待機しています

debugPrint(Color.red)
debugPrint(Color(red: 1.0, green: 0.0, blue: 0.0))
debugPrint(Color(red: 1.0, green: 0.3, blue: 0.0))
debugPrint(Color(.sRGB, red: 1.0, green: 0.0, blue: 0.5, opacity: 0.3))
debugPrint(Color(hue: 1.0, saturation: 0.0, brightness: 1.0))
debugPrint(Color(.displayP3, red: 1.0, green: 0.0, blue: 0.0, opacity: 1.0).description)

red
#FF0000FF
#FF4C00FF
#FF00804D
#FFFFFFFF
"DisplayP3(red: 1.0, green: 0.0, blue: 0.0, opacity: 1.0)"

ご覧のとおり、Color.redのようなものは "red"をダンプするだけですが、コードによって(つまり、カラーピッカーから)生成された単純なRGBカラーを使用している場合、これはそれほど悪くありません。

extension SwiftUI.Color {
    var redComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let r1 = val.index(val.startIndex, offsetBy: 1)
        let r2 = val.index(val.startIndex, offsetBy: 2)
        return Double(Int(val[r1...r2], radix: 16)!) / 255.0
    }

    var greenComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let g1 = val.index(val.startIndex, offsetBy: 3)
        let g2 = val.index(val.startIndex, offsetBy: 4)
        return Double(Int(val[g1...g2], radix: 16)!) / 255.0
    }

    var blueComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let b1 = val.index(val.startIndex, offsetBy: 5)
        let b2 = val.index(val.startIndex, offsetBy: 6)
        return Double(Int(val[b1...b2], radix: 16)!) / 255.0
    }

    var opacityComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let b1 = val.index(val.startIndex, offsetBy: 7)
        let b2 = val.index(val.startIndex, offsetBy: 8)
        return Double(Int(val[b1...b2], radix: 16)!) / 255.0
    }
}
2
Nicola Ferruzzi