forked from donjin123/ColorPickerWheel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorSlider.swift
154 lines (134 loc) · 5.03 KB
/
ColorSlider.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//
// ColorSlider.swift
// color
//
// Created by Donjin_master on 05/10/2018.
// Copyright © 2018 Donjin. All rights reserved.
//
import UIKit
public protocol ColorSliderProtocol {
func colorSlider(bright: CGFloat)
}
@IBDesignable
public class ColorSlider: UIView {
var delegate: ColorSliderProtocol?
private var colorVal: UIColor = UIColor.white
@IBInspectable
public var selectedColor: UIColor {
set {
self.colorVal = newValue
self.createBackground()
}
get {
return self.colorVal
}
}
private var background: UIImageView?
/// width with scale
private var widths: Int!
/// height with scale
private var heights: Int!
private var scale = UIScreen.main.scale
private var thumb: UIView!
private var lastLocation: CGPoint!
private let gray = UIColor(red: 0.596, green: 0.596, blue: 0.596, alpha: 1)
public override init(frame: CGRect) {
super.init(frame: frame)
guard self.bounds != CGRect.zero else {
// avoid error when xib preview
return
}
self.prepare()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
guard self.bounds != CGRect.zero else {
// avoid error when xib preview
return
}
self.prepare()
}
override public func prepareForInterfaceBuilder() {
// For storyboard/ xib only
// won't run at program initialization
self.prepare()
}
private func prepare() {
self.widths = Int(self.bounds.width * self.scale)
self.heights = Int(self.bounds.height * self.scale)
self.createBackground()
self.createThumb()
}
}
// MARK: background
extension ColorSlider {
private func createBackground() {
if self.background != nil {
self.background!.removeFromSuperview()
}
let space = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: nil, width: self.widths, height: self.heights, bitsPerComponent: 8, bytesPerRow: self.widths * 4, space: space, bitmapInfo: Pixel.bitmapInfo)!
let buffer = context.data!
var hue: CGFloat = 0
var sat: CGFloat = 0
var alpha: CGFloat = 0
self.colorVal.getHue(&hue, saturation: &sat, brightness: nil, alpha: &alpha)
let fWidths = CGFloat(self.widths)
let pixels = buffer.bindMemory(to: Pixel.self, capacity: self.widths * self.heights)
for y in 0 ..< self.heights {
for x in 0 ..< self.widths {
let bright = 1 - CGFloat(x) / fWidths
let pixel = self.pixel(hue: hue, sat: sat, alpha: alpha, bright: bright)
pixels[y * self.widths + x] = pixel
}
}
let cgImage = context.makeImage()!
let img = UIImage(cgImage: cgImage, scale: self.scale, orientation: .up)
self.background = UIImageView(image: img)
self.background!.layer.borderColor = self.gray.cgColor
self.background!.layer.borderWidth = 1
self.background!.layer.cornerRadius = 0.5 * self.bounds.height
self.background!.layer.masksToBounds = true
self.insertSubview(self.background!, at: 0)
}
private func pixel(hue: CGFloat, sat: CGFloat, alpha: CGFloat, bright: CGFloat) -> Pixel {
let value = UIColor(hue: hue, saturation: sat, brightness: bright, alpha: alpha)
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)
let pixel = Pixel(red: UInt8(red * 255.0),
green: UInt8(green * 255.0),
blue: UInt8(blue * 255.0),
alpha: UInt8(alpha * 255.0))
return pixel
}
}
// MARK: thumb
extension ColorSlider {
private func createThumb() {
let frame = CGRect(x: 0, y: 0, width: 1.5*self.bounds.height, height: 1.5*self.bounds.height)
self.thumb = UIView(frame: frame)
self.thumb.layer.cornerRadius = 0.5 * frame.height
self.thumb.layer.borderColor = self.gray.cgColor
self.thumb.layer.borderWidth = 1
self.thumb.layer.backgroundColor = UIColor.white.cgColor
self.thumb.center = CGPoint(x: 0,
y: 0.5 * self.bounds.height)
self.addSubview(self.thumb)
let pan = UIPanGestureRecognizer(target: self, action: #selector(self.detectPan(ges:)))
self.thumb.addGestureRecognizer(pan)
}
@objc private func detectPan(ges: UIPanGestureRecognizer) {
if ges.state == .began {
self.lastLocation = self.thumb.center
} else {
let translation = ges.translation(in: self)
var x = max(0, self.lastLocation.x + translation.x)
x = min(x, self.bounds.width)
self.thumb.center = CGPoint(x: x, y: self.thumb.center.y)
self.delegate?.colorSlider(bright: 1 - x/self.bounds.width)
}
}
}