问题
Hi i am trying to write colour picker in swift that looks like this.
But so far I managed this.
Draw circle was easy, heres code...
fileprivate func setupScene(){
let circlePath: UIBezierPath = UIBezierPath(arcCenter: CGPoint(x: self.wheelView.frame.width/2, y: self.wheelView.frame.height/2), radius: CGFloat(self.wheelView.frame.height/2), startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
//color inside circle
shapeLayer.fillColor = UIColor.clear.cgColor
//colored border of circle
shapeLayer.strokeColor = UIColor.purple.cgColor
//width size of border
shapeLayer.lineWidth = 10
wheelView.layer.addSublayer(shapeLayer)
}
@IBOutlet var wheelView: UIView!
But now I don't know how to insert rainbow colours ... I tried CAGradientLayer but it was not visible. Any good advice?
回答1:
Details
- Xcode 9.1, swift 4
- Xcode 10.2.1 (10E1001), Swift 5
Solution
The code was taken from https://github.com/joncardasis/ChromaColorPicker
import UIKit
class RainbowCircle: UIView {
private var radius: CGFloat {
return frame.width>frame.height ? frame.height/2 : frame.width/2
}
private var stroke: CGFloat = 10
private var padding: CGFloat = 5
//MARK: - Drawing
override func draw(_ rect: CGRect) {
super.draw(rect)
drawRainbowCircle(outerRadius: radius - padding, innerRadius: radius - stroke - padding, resolution: 1)
}
init(frame: CGRect, lineHeight: CGFloat) {
super.init(frame: frame)
stroke = lineHeight
}
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
/*
Resolution should be between 0.1 and 1
*/
private func drawRainbowCircle(outerRadius: CGFloat, innerRadius: CGFloat, resolution: Float) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.saveGState()
context.translateBy(x: self.bounds.midX, y: self.bounds.midY) //Move context to center
let subdivisions:CGFloat = CGFloat(resolution * 512) //Max subdivisions of 512
let innerHeight = (CGFloat.pi*innerRadius)/subdivisions //height of the inner wall for each segment
let outterHeight = (CGFloat.pi*outerRadius)/subdivisions
let segment = UIBezierPath()
segment.move(to: CGPoint(x: innerRadius, y: -innerHeight/2))
segment.addLine(to: CGPoint(x: innerRadius, y: innerHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: outterHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: -outterHeight/2))
segment.close()
//Draw each segment and rotate around the center
for i in 0 ..< Int(ceil(subdivisions)) {
UIColor(hue: CGFloat(i)/subdivisions, saturation: 1, brightness: 1, alpha: 1).set()
segment.fill()
//let lineTailSpace = CGFloat.pi*2*outerRadius/subdivisions //The amount of space between the tails of each segment
let lineTailSpace = CGFloat.pi*2*outerRadius/subdivisions
segment.lineWidth = lineTailSpace //allows for seemless scaling
segment.stroke()
//Rotate to correct location
let rotate = CGAffineTransform(rotationAngle: -(CGFloat.pi*2/subdivisions)) //rotates each segment
segment.apply(rotate)
}
context.translateBy(x: -self.bounds.midX, y: -self.bounds.midY) //Move context back to original position
context.restoreGState()
}
}
Usage
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let rainbowCircle = RainbowCircle(frame: CGRect(x: 50, y: 50, width: 240, height: 420), lineHeight: 5)
rainbowCircle.backgroundColor = .clear
view.addSubview(rainbowCircle)
}
}
Result
来源:https://stackoverflow.com/questions/44262374/swift-rainbow-colour-circle