swift 如何提取拇指位置最小轨迹图像的渐变色?

0dxa2lsx  于 2022-12-28  发布在  Swift
关注(0)|答案(1)|浏览(114)

我想将滑块颜色更改为与最小轨道颜色相同。我需要在滑块沿滑块移动时提取滑块位置的颜色。我想让滑块滑块看起来像这样,并在滑块沿滑块移动时根据最小轨道渐变颜色更改颜色。

下面是我创建的渐变的代码

func setSlider(slider:UISlider) {
            let tgl = CAGradientLayer()
            let frame = CGRect(x: 0.0, y: 0.0, width: slider.bounds.width, height: 10.0)
            tgl.frame = frame
            tgl.colors = [UIColor.black.cgColor, UIColor.red.cgColor, UIColor.yellow.cgColor, UIColor.green.cgColor]
            tgl.borderWidth = 1.0
            tgl.borderColor = UIColor.gray.cgColor
            tgl.cornerRadius = 5.0
            tgl.endPoint = CGPoint(x: 1.0, y:  1.0)
            tgl.startPoint = CGPoint(x: 0.0, y:  1.0)
            UIGraphicsBeginImageContextWithOptions(tgl.frame.size, false, 10.0)
            tgl.render(in: UIGraphicsGetCurrentContext()!)
            let backgroundImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            slider.setMaximumTrackImage(getBgImage(width: slider.bounds.width), for: .normal)
            slider.setMinimumTrackImage(backgroundImage, for: .normal)
}
I tried to fetch color using the following code:

    let color = sliderRating.minimumTrackImage(for: .normal)?.getPixelColor(point: CGPoint(x: Int(sender.value), y: 1))
    
    func getPixelColor(point: CGPoint) -> UIColor? {
                   guard let cgImage = cgImage else { return nil }
        
                   let width = Int(size.width)
                   let height = Int(size.height)
                   let colorSpace = CGColorSpaceCreateDeviceRGB()
        
                   guard let context = CGContext(data: nil,
                                                 width: width,
                                                 height: height,
                                                 bitsPerComponent: 8,
                                                 bytesPerRow: width * 4,
                                                 space: colorSpace,
                                                 bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
                       else {
                           return nil
                   }
     
                   context.draw(cgImage, in: CGRect(origin: .zero, size: size))
        
                   guard let pixelBuffer = context.data else { return nil }
        
                   let pointer = pixelBuffer.bindMemory(to: UInt32.self, capacity: width * height)
                   let pixel = pointer[Int(point.y) * width + Int(point.x)]
        
                   let r: CGFloat = CGFloat(red(for: pixel))   / 255
                   let g: CGFloat = CGFloat(green(for: pixel)) / 255
                   let b: CGFloat = CGFloat(blue(for: pixel))  / 255
                   let a: CGFloat = CGFloat(alpha(for: pixel)) / 255
        
                return UIColor(red: r, green: g, blue: b, alpha: a)
               }
        
               private func alpha(for pixelData: UInt32) -> UInt8 {
                   return UInt8((pixelData >> 24) & 255)
               }
        
               private func red(for pixelData: UInt32) -> UInt8 {
                   return UInt8((pixelData >> 16) & 255)
               }
        
               private func green(for pixelData: UInt32) -> UInt8 {
                   return UInt8((pixelData >> 8) & 255)
               }
        
               private func blue(for pixelData: UInt32) -> UInt8 {
                   return UInt8((pixelData >> 0) & 255)
               }
        
               private func rgba(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -> UInt32 {
                   return (UInt32(alpha) << 24) | (UInt32(red) << 16) | (UInt32(green) << 8) | (UInt32(blue) << 0)
}

下面是我在堆栈溢出上发现的一个类似问题,以供参考:
How can I extract the uislider gradient color at the thumb position?
我试着从图像中提取像素颜色,但它只给我白色,灰色和较深的灰色阴影,但我的轨道有颜色范围从黑色到绿色。
我得到的输出是这样的:

bxgwgixi

bxgwgixi1#

问题是如何确定颜色的point
您显示的代码:

let color = sliderRating.minimumTrackImage(for: .normal)?.getPixelColor(point: CGPoint(x: Int(sender.value), y: 1))

很难调试。
我们把它分开:

// safely unwrap the optional to make sure we get a valid image
    if let minImg = sender.minimumTrackImage(for: .normal) {
        let x = Int(sender.value)
        let y = 1
        let point = CGPoint(x: x, y: y)
        
        // to debug this:
        print("point:", point)

        // safely unwrap the optional returned color
        if let color = minImg.getPixelColor(pos: point) {
            // do something with color
        }
    }

默认情况下,滑块的值在0.01.0之间,所以当你拖动滑块时,你会在调试控制台中看到以下输出:

// lots of these
point: (0.0, 1.0)
point: (0.0, 1.0)
point: (0.0, 1.0)
point: (0.0, 1.0)
point: (0.0, 1.0)
// then when you final get all the way to the right
point: (1.0, 1.0)

正如你所看到的,你没有得到你想要的点在你的形象。
你别客气,但如果做了这样的事:

sliderRating.minimumValue = 100
    sliderRating.maximumValue = 120

您的x的范围将从100120。同样,不是您想要的点。
与使用.value不同,对于x,您希望获得缩略图rect的水平中心,对于y,您希望获得image size的垂直中心。
试着这样做:

@objc func sliderRatingValueChanged(_ sender: UISlider) {

    // get the slider's trackRect
    let trackR = sender.trackRect(forBounds: sender.bounds)
    // get the slider's thumbRect
    let thumbR = sender.thumbRect(forBounds: sender.bounds, trackRect: trackR, value: sender.value)

    // get the slider's minimumTrackImage
    if let minImg = sender.minimumTrackImage(for: .normal) {
        // we want point.x to be thumb rect's midX
        // we want point.y to be 1/2 the height of the min track image
        let point = CGPoint(x: thumbR.midX, y: minImg.size.height * 0.5)

        // for debugging:
        print("point:", point)

        // get the color at point
        if let color = minImg.getPixelColor(point: point) {
            // set tint color of thumb
            sender.thumbTintColor = color
        }
    }

    // now do something with the slider's value?
    let value = sender.value

}

相关问题