• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SwiftUI实现Codable的伪Color

武飞扬头像
ヒーロー
帮助1

痛点

在使用SwiftUI时,可能需要将Color转换为JSON以便存储、传输,然而Color本身又难以get数值属性。

虽然可以写一个只包含rgb的颜色类,但是如果使用了ColorPicker这样的View又只能使用Color或者CGColor来实现,因此在重写ColorPicker和重写Color之间我选择重写Color。

实现目标

  • Codable是最起码的
  • 和Color或者CGColor的互转
  • 在ColorPicker中大概能使用

SwiftUI中的Color和UIColor

Color

Color类虽然非常直观易用,内置了很多颜色,但是持久化存储挺麻烦的,好在可以和CGColor互转,于是就开始研究CGColor的存储

CGColor

相对Color而言,CGColor就看起来容易存储许多,不过有一点麻烦的是色彩空间的指定,所以我的实现里面只有sRGB和p3,其他色彩空间同理。

MyColor的实现

属性

var r: CGFloat
var g: CGFloat
var b: CGFloat
var alpha: CGFloat
var space : Space = .srgb

enum Space: String, Codable {
    case srgb
    case p3
}

和Color的转换

// 使用相似的方法创建
init(r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat) {
    self.r = r
    self.g = g
    self.b = b
    self.alpha = a
}

func toColor() -> Color {
    return Color(toCGColor()).opacity(alpha)
}

和CGColor的转换

init(cgcolor: CGColor) {
    let colorSpaceName : CGColorSpace = cgcolor.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
    let colorComponents = cgcolor.components!
    if colorComponents.count == 4 {
        r = colorComponents[0]
        g = colorComponents[1]
        b = colorComponents[2]
        alpha = colorComponents[3]
    } else {
        fatalError("cant convert cgcolor to mycolor")
    }
    switch colorSpaceName {
    case CGColorSpace(name: CGColorSpace.sRGB): space = Space.srgb
    case CGColorSpace(name: CGColorSpace.displayP3): space = Space.p3
    default:space = Space.srgb
    }
}

func toCGColor() -> CGColor {
    return CoreGraphics.CGColor(colorSpace: colorSpace, components: [r,g,b,alpha])!
}
学新通

使用示例

import SwiftUI

struct ColorPickerWithMyColor: View {
    @Binding var color: MyColor
    @State var colorTemp : CGColor = .random()

    var body: some View {
        HStack {
            ColorPicker(selection: $colorTemp){
//                let c = Color.random()
            }
            .onChange(of: colorTemp, perform: { newColor in
                color = MyColor(cgcolor: newColor)
            })
        }
        .onAppear(perform: {
            colorTemp = color.toCGColor()
        })
    }
}
学新通

MyColor的完整代码

import SwiftUI

class MyColor: Codable {
    var r: CGFloat
    var g: CGFloat
    var b: CGFloat
    var alpha: CGFloat
    var space : Space = .srgb
    
    enum CodingKeys: String, CodingKey {
        case r,g,b,alpha,space
    }
    
    enum Space: String, Codable {
        case srgb
        case p3
    }
    
    init(r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat) {
        self.r = r
        self.g = g
        self.b = b
        self.alpha = a
    }
    
    init(cgcolor: CGColor) {
        let colorSpaceName : CGColorSpace = cgcolor.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
        let colorComponents = cgcolor.components!
        if colorComponents.count == 4 {
            r = colorComponents[0]
            g = colorComponents[1]
            b = colorComponents[2]
            alpha = colorComponents[3]
        } else {
            fatalError("cant convert cgcolor to mycolor")
        }
        switch colorSpaceName {
        case CGColorSpace(name: CGColorSpace.sRGB): space = Space.srgb
        case CGColorSpace(name: CGColorSpace.displayP3): space = Space.p3
        default:space = Space.srgb
        }
    }
    
    func toCGColor() -> CGColor {
        return CoreGraphics.CGColor(colorSpace: colorSpace, components: [r,g,b,alpha])!
    }
    
    func toColor() -> Color {
        return Color(toCGColor()).opacity(alpha)
    }
    
    var colorSpace: CGColorSpace {
        switch space {
        case .srgb : return CGColorSpace(name: CGColorSpace.sRGB)!
        case .p3 : return CGColorSpace(name: CGColorSpace.displayP3)!
        }
    }
    
    static func random() -> MyColor {
        return MyColor(r: .random(in: 0...1), g: .random(in: 0...1), b: .random(in: 0...1), a: .random(in: 0.5...1))
    }
    
    static func random() -> CGColor {
        return MyColor.random().toCGColor()
    }
    
}

extension MyColor: Equatable {
    static func == (lop: MyColor, rop: MyColor) -> Bool {
        return lop.toCGColor() == rop.toCGColor()
    }
}

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgicgii
系列文章
更多 icon
同类精品
更多 icon
继续加载