簡體   English   中英

如何使用CAGradientLayer繪制漸變色輪?

[英]How to draw a gradient color wheel using CAGradientLayer?

我從這些鏈接中得到了一些參考 -

我已經經歷了“HSV色彩空間”的概念。 但我想在CAGradientLayer的幫助下使用RGB繪制色輪。

以下是使用簡單的RGB顏色數組和UIBezierPath制作色輪的代碼片段 -

func drawColorWheel()
{
    context?.saveGState()

    range = CGFloat(100.00 / CGFloat(colorArray.count))

    for k in 0 ..< colorArray.count
    {

        drawSlice(startPercent: CGFloat(k) * range, endPercent: CGFloat(CGFloat(k + 1) * range), color: colorArray.object(at: k) as! UIColor)
    }

    context?.restoreGState()
}

func drawSlice(startPercent: CGFloat, endPercent: CGFloat, color: UIColor)
{        
    let startAngle = getAngleAt(percentage: startPercent)
    let endAngle = getAngleAt(percentage: endPercent)

    let path =  getArcPath(startAngle: startAngle, endAngle: endAngle)
    color.setFill()
    path.fill()
}

其中getAngleAt()getArcPath()是使用角度繪制路徑的私有函數。

這是我的代碼的最終輸出 - 色輪

現在,我的問題是如何為這些顏色提供漸變效果,以便每種顏色與漸變顏色層混合?

一種方法是構建圖像並手動操作像素緩沖區:

  • 創建一定大小和特定類型的CGContext ;
  • 通過data屬性訪問其數據緩沖區;
  • 將其重新綁定到易於操作緩沖區的東西(我使用Pixel ,一個用於Pixel的32位表示的struct );
  • 逐個循環通過像素,將其轉換為此圖像中圓圈的angleradius ;
  • 如果它在圓圈內,則創建一個適當顏色的像素; 如果不是,則將其設為零alpha像素。

所以在Swift 3中:

func buildHueCircle(in rect: CGRect, radius: CGFloat, scale: CGFloat = UIScreen.main.scale) -> UIImage? {
    let width = Int(rect.size.width * scale)
    let height = Int(rect.size.height * scale)
    let center = CGPoint(x: width / 2, y: height / 2)

    let space = CGColorSpaceCreateDeviceRGB()
    let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: space, bitmapInfo: Pixel.bitmapInfo)!

    let buffer = context.data!

    let pixels = buffer.bindMemory(to: Pixel.self, capacity: width * height)
    var pixel: Pixel
    for y in 0 ..< height {
        for x in 0 ..< width {
            let angle = fmod(atan2(CGFloat(x) - center.x, CGFloat(y) - center.y) + 2 * .pi, 2 * .pi)
            let distance = hypot(CGFloat(x) - center.x, CGFloat(y) - center.y)

            let value = UIColor(hue: angle / 2 / .pi, saturation: 1, brightness: 1, alpha: 1)

            var red: CGFloat = 0
            var green: CGFloat = 0
            var blue: CGFloat = 0
            var alpha: CGFloat = 0
            value.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

            if distance <= (radius * scale) {
                pixel = Pixel(red:   UInt8(red * 255),
                              green: UInt8(green * 255),
                              blue:  UInt8(blue * 255),
                              alpha: UInt8(alpha * 255))
            } else {
                pixel = Pixel(red: 255, green: 255, blue: 255, alpha: 0)
            }
            pixels[y * width + x] = pixel
        }
    }

    let cgImage = context.makeImage()!
    return UIImage(cgImage: cgImage, scale: scale, orientation: .up)
}

哪里

struct Pixel: Equatable {
    private var rgba: UInt32

    var red: UInt8 {
        return UInt8((rgba >> 24) & 255)
    }

    var green: UInt8 {
        return UInt8((rgba >> 16) & 255)
    }

    var blue: UInt8 {
        return UInt8((rgba >> 8) & 255)
    }

    var alpha: UInt8 {
        return UInt8((rgba >> 0) & 255)
    }

    init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
        rgba = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0)
    }

    static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue

    static func ==(lhs: Pixel, rhs: Pixel) -> Bool {
        return lhs.rgba == rhs.rgba
    }
}

產量:

恆定飽和色輪

或者您可以根據半徑調整亮度或飽和度:

調整亮度

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM