2016-09-23 2 views
4

Я работаю над приложением, которое общается с ардуино для управления светодиодными световыми полосками RGB. Я пытаюсь реализовать подборщик цветов, когда вы касаетесь изображения цветового спектра и получаете UIColor пикселя, который был затронут.IOS Color Picker in Swift 3.0

Я хочу, чтобы пользователь мог касаться в любом месте изображения цветового спектра и менять цвет на цвет, который они касаются. для этого мне либо нужны номера 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. Я портировали его на как могу, но я получаю следующее сообщение об ошибке, что я не уверен, как это исправить:

enter image description here

и

enter image description here

для первой ошибки я, кажется, разрешил его, изменив код на следующий, но я не уверен, что это правильно.

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) 
} 

Что касается второго ошибки ors Я просто не уверен, как переключиться на использование шага. (от:, до:, 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) 
} 
} 

Я бы очень признателен за любую помощь, которую вы все можете предложить. Я также открыт для совершенно разных предложений, если у вас есть лучший способ достичь моей первоначальной цели выбора цвета, которую пользователь может коснуться!

ответ

1

1) Для этой строки кода для работы:

let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(_:))) 

вам необходимо предварять подчеркнуть _ характер параметра в этом методе:

func touchedColor(_ gestureRecognizer: UILongPressGestureRecognizer){ } 

2) Когда с использованием шага, правильный синтаксис:

for y in stride(from: 0, to: rect.height, by: elementSize) { 

Так полный for-cycle дополнительные исправления в Swift 3 версия должна выглядеть следующим образом:

for y in stride(from: 0, 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 stride(from: 0, 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)) 
    } 
} 
+0

Отлично! Это именно то, что меня подвело! Еще один вопрос, хотя у меня есть переменная для значений красного, зеленого и синего. Как установить эти переменные на цвет, который будет затронут на основе кода выше? – BLF0005

+0

Я предполагаю, что вы имеете в виду let color = UIColor(): так просто 'let color = UIColor (red: green: white:)' method. И помог ли мой ответ? :) – pedrouan