我正在开发一个与arduino通信以控制RGB LED灯带的应用程序。我正在尝试实现一个颜色选择器,在其中触摸颜色谱图像并获取所触摸像素的UIColor。
我希望用户能够在颜色谱图像的任何位置触摸并将颜色更改为他们所触摸的颜色。要做到这一点,我需要RGB数字或他们所触摸的像素的UIColor。
我已经找到了以下代码,但尝试实现没有成功。以下是原作者的描述:
“这是我制作的最简单的代码之一。它只是一个轻量级的UIView,允许您指定元素大小(如果您想要阻止区域,则elementSize> 1)。它在接口生成器中绘制自己,因此您可以设置元素大小并查看后果。只需在接口生成器中将一个视图设置为此类,然后将自己设置为代理即可。它会告诉您什么时候有人在其上点击或拖动,并且该位置的UIColor。它会将自己绘制到其自身的边界上,除了这个类之外不需要其他任何东西,也不需要图片。”
我希望用户能够在颜色谱图像的任何位置触摸并将颜色更改为他们所触摸的颜色。要做到这一点,我需要RGB数字或他们所触摸的像素的UIColor。
我已经找到了以下代码,但尝试实现没有成功。以下是原作者的描述:
“这是我制作的最简单的代码之一。它只是一个轻量级的UIView,允许您指定元素大小(如果您想要阻止区域,则elementSize> 1)。它在接口生成器中绘制自己,因此您可以设置元素大小并查看后果。只需在接口生成器中将一个视图设置为此类,然后将自己设置为代理即可。它会告诉您什么时候有人在其上点击或拖动,并且该位置的UIColor。它会将自己绘制到其自身的边界上,除了这个类之外不需要其他任何东西,也不需要图片。”
import UIKit
internal protocol HSBColorPickerDelegate : NSObjectProtocol {
func HSBColorColorPickerTouched(sender:HSBColorPicker, color:UIColor, point:CGPoint, state:UIGestureRecognizerState)
}
@IBDesignable
class HSBColorPicker : UIView {
weak internal var delegate: HSBColorPickerDelegate?
let saturationExponentTop:Float = 2.0
let saturationExponentBottom:Float = 1.3
@IBInspectable var elementSize: CGFloat = 1.0 {
didSet {
setNeedsDisplay()
}
}
private func initialize() {
self.clipsToBounds = true
let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(_:)))
touchGesture.minimumPressDuration = 0
touchGesture.allowableMovement = CGFloat.max
self.addGestureRecognizer(touchGesture)
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
for y in (0 as CGFloat).stride(to: rect.height, by: elementSize) {
var saturation = y < rect.height / 2.0 ? CGFloat(2 * y) / rect.height : 2.0 * CGFloat(rect.height - y) / rect.height
saturation = CGFloat(powf(Float(saturation), y < rect.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
let brightness = y < rect.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(rect.height - y) / rect.height
for x in (0 as CGFloat).stride(to: rect.width, by: elementSize) {
let hue = x / rect.width
let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, CGRect(x:x, y:y, width:elementSize,height:elementSize))
}
}
}
func getColorAtPoint(point:CGPoint) -> UIColor {
let roundedPoint = CGPoint(x:elementSize * CGFloat(Int(point.x / elementSize)),
y:elementSize * CGFloat(Int(point.y / elementSize)))
var saturation = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(2 * roundedPoint.y) / self.bounds.height
: 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
saturation = CGFloat(powf(Float(saturation), roundedPoint.y < self.bounds.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
let brightness = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
let hue = roundedPoint.x / self.bounds.width
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
}
func getPointForColor(color:UIColor) -> CGPoint {
var hue:CGFloat=0;
var saturation:CGFloat=0;
var brightness:CGFloat=0;
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil);
var yPos:CGFloat = 0
let halfHeight = (self.bounds.height / 2)
if (brightness >= 0.99) {
let percentageY = powf(Float(saturation), 1.0 / saturationExponentTop)
yPos = CGFloat(percentageY) * halfHeight
} else {
//use brightness to get Y
yPos = halfHeight + halfHeight * (1.0 - brightness)
}
let xPos = hue * self.bounds.width
return CGPoint(x: xPos, y: yPos)
}
func touchedColor(gestureRecognizer: UILongPressGestureRecognizer){
let point = gestureRecognizer.locationInView(self)
let color = getColorAtPoint(point)
self.delegate?.HSBColorColorPickerTouched(self, color: color, point: point, state:gestureRecognizer.state)
}
}
我不确定如何在Swift 3.0中使此代码工作。我已经尽力移植了它,但我收到以下错误,我不确定该如何解决:
并且
对于第一个错误,我似乎已经通过将代码更改为以下内容来解决了,但我不确定这是否正确。
private func initialize() {
self.clipsToBounds = true
let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(gestureRecognizer:)))
touchGesture.minimumPressDuration = 0
touchGesture.allowableMovement = CGFloat.greatestFiniteMagnitude
self.addGestureRecognizer(touchGesture)
}
关于第二个错误,我不确定如何切换到使用步长(from:、to:、by:)。
这是我尝试将其移植到Swift 3.0的代码:
import UIKit
internal protocol HSBColorPickerDelegate : NSObjectProtocol {
func HSBColorColorPickerTouched(sender:HSBColorPicker, color:UIColor, point:CGPoint, state:UIGestureRecognizerState)
}
@IBDesignable
class HSBColorPicker : UIView {
weak internal var delegate: HSBColorPickerDelegate?
let saturationExponentTop:Float = 2.0
let saturationExponentBottom:Float = 1.3
@IBInspectable var elementSize: CGFloat = 1.0 {
didSet {
setNeedsDisplay()
}
}
private func initialize() {
self.clipsToBounds = true
let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(gestureRecognizer:)))
touchGesture.minimumPressDuration = 0
touchGesture.allowableMovement = CGFloat.greatestFiniteMagnitude
self.addGestureRecognizer(touchGesture)
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
for y in (0 as CGFloat).stride(to: rect.height, by: elementSize) {
var saturation = y < rect.height / 2.0 ? CGFloat(2 * y) / rect.height : 2.0 * CGFloat(rect.height - y) / rect.height
saturation = CGFloat(powf(Float(saturation), y < rect.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
let brightness = y < rect.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(rect.height - y) / rect.height
for x in (0 as CGFloat).stride(to: rect.width, by: elementSize) {
let hue = x / rect.width
let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
context!.setFillColor(color.cgColor)
context!.fill(CGRect(x:x, y:y, width:elementSize,height:elementSize))
}
}
}
func getColorAtPoint(point:CGPoint) -> UIColor {
let roundedPoint = CGPoint(x:elementSize * CGFloat(Int(point.x / elementSize)),
y:elementSize * CGFloat(Int(point.y / elementSize)))
var saturation = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(2 * roundedPoint.y) / self.bounds.height
: 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
saturation = CGFloat(powf(Float(saturation), roundedPoint.y < self.bounds.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
let brightness = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
let hue = roundedPoint.x / self.bounds.width
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
}
func getPointForColor(color:UIColor) -> CGPoint {
var hue:CGFloat=0;
var saturation:CGFloat=0;
var brightness:CGFloat=0;
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil);
var yPos:CGFloat = 0
let halfHeight = (self.bounds.height / 2)
if (brightness >= 0.99) {
let percentageY = powf(Float(saturation), 1.0 / saturationExponentTop)
yPos = CGFloat(percentageY) * halfHeight
} else {
//use brightness to get Y
yPos = halfHeight + halfHeight * (1.0 - brightness)
}
let xPos = hue * self.bounds.width
return CGPoint(x: xPos, y: yPos)
}
func touchedColor(gestureRecognizer: UILongPressGestureRecognizer){
let point = gestureRecognizer.location(in: self)
let color = getColorAtPoint(point: point)
self.delegate?.HSBColorColorPickerTouched(sender: self, color: color, point: point, state:gestureRecognizer.state)
}
}
我非常感谢你们能提供的任何帮助。如果你有更好的方法来实现我的原始目标 - 用户可以触摸的颜色选择器,我也愿意听取完全不同的建议!
let color = UIColor(red: green: white:)
方法即可。我的回答有帮到你吗? :) - pedrouan