Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b4357f1
Showing
5 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Pod::Spec.new do |spec| | ||
spec.name = 'GradientKit' | ||
spec.summary = 'A simpler way to implement simple gradients on iOS.' | ||
spec.version = '1.0' | ||
spec.license = { :type => 'MIT' } | ||
spec.authors = { 'Joe Fabisevich' => 'github@fabisevi.ch' } | ||
spec.source_files = 'Source/*.swift' | ||
spec.homepage = 'https://github.com/mergesort' | ||
spec.source = { :git => 'https://github.com/mergesort/GradientKit.git', :tag => "#{spec.version}" } | ||
|
||
spec.ios.deployment_target = '9.0' | ||
spec.requires_arc = true | ||
spec.social_media_url = 'https://twitter.com/mergesort' | ||
spec.framework = 'UIKit' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import UIKit | ||
|
||
public struct GradientComponents { | ||
|
||
let color: UIColor | ||
let location: Double | ||
} | ||
|
||
public protocol Gradient { | ||
|
||
var startPoint: CGPoint { get } | ||
func makeGradientComponents() -> [GradientComponents] | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import UIKit | ||
|
||
public final class GradientView: UIView { | ||
|
||
private let gradientLayer = CAGradientLayer() | ||
|
||
public var gradient: Gradient = UniformGradient(colors: [.white]) { | ||
didSet { | ||
self.generateGradient() | ||
} | ||
} | ||
|
||
// MARK: Initializers | ||
|
||
public override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
|
||
self.setup() | ||
} | ||
|
||
@available(*, unavailable) | ||
public required init?(coder aDecoder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
public override func layoutSubviews() { | ||
super.layoutSubviews() | ||
|
||
self.gradientLayer.frame = self.bounds | ||
} | ||
} | ||
|
||
private extension GradientView { | ||
|
||
func setup() { | ||
self.isUserInteractionEnabled = false | ||
self.layer.addSublayer(self.gradientLayer) | ||
} | ||
|
||
func generateGradient() { | ||
self.gradientLayer.startPoint = self.gradient.startPoint | ||
|
||
let components = self.gradient.makeGradientComponents() | ||
let colors = components.map { $0.color.cgColor } | ||
let locations = components.map { NSNumber(value: $0.location) } | ||
|
||
self.gradientLayer.colors = colors | ||
self.gradientLayer.locations = locations | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import Foundation | ||
|
||
public enum GradientDirection { | ||
|
||
case darkToLight | ||
case lightToDark | ||
} | ||
|
||
public struct PercentageGradient: Gradient { | ||
|
||
public let baseColor: UIColor | ||
public let direction: GradientDirection | ||
public let percentage: CGFloat | ||
public let startPoint: CGPoint | ||
|
||
public init(baseColor: UIColor, direction: GradientDirection, percentage: CGFloat, startPoint: CGPoint = CGPoint(x: 0.5, y: 0.0)) { | ||
self.baseColor = baseColor | ||
self.direction = direction | ||
self.percentage = percentage | ||
self.startPoint = startPoint | ||
} | ||
} | ||
|
||
public extension PercentageGradient { | ||
|
||
func makeGradientComponents() -> [GradientComponents] { | ||
switch self.direction { | ||
|
||
case .darkToLight: | ||
return [ | ||
GradientComponents( | ||
color: self.darkerColor(from: baseColor), | ||
location: 0.0 | ||
), | ||
GradientComponents( | ||
color: self.lighterColor(from: baseColor), | ||
location: 1.0 | ||
) | ||
] | ||
|
||
case .lightToDark: | ||
return [ | ||
GradientComponents( | ||
color: self.lighterColor(from: baseColor), | ||
location: 0.0 | ||
), | ||
GradientComponents( | ||
color: self.darkerColor(from: baseColor), | ||
location: 1.0 | ||
) | ||
] | ||
} | ||
} | ||
|
||
} | ||
|
||
|
||
extension PercentageGradient { | ||
|
||
func lighterColor(from color: UIColor) -> UIColor { | ||
switch self.direction { | ||
|
||
case .darkToLight: | ||
return color | ||
|
||
case .lightToDark: | ||
return (color.changedBrightness(byPercentage: self.percentage) ?? UIColor.white) | ||
} | ||
} | ||
|
||
func darkerColor(from color: UIColor) -> UIColor { | ||
switch self.direction { | ||
|
||
case .darkToLight: | ||
return (color.changedBrightness(byPercentage: -self.percentage) ?? UIColor.black) | ||
|
||
case .lightToDark: | ||
return color | ||
} | ||
} | ||
} | ||
|
||
private extension UIColor { | ||
|
||
func hsba() -> (hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat)? { | ||
var hue: CGFloat = .nan | ||
var saturation: CGFloat = .nan | ||
var brightness: CGFloat = .nan | ||
var alpha: CGFloat = .nan | ||
|
||
guard self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) else { return nil } | ||
|
||
return (hue: hue, saturation: saturation, brightness: brightness, alpha: alpha) | ||
} | ||
|
||
func changedBrightness(byPercentage percent: CGFloat) -> UIColor? { | ||
guard percent != 0 else { return self.copy() as? UIColor } | ||
|
||
guard let hsba = self.hsba() else { return nil } | ||
|
||
let percentage: CGFloat = min(max(percent, -1), 1) | ||
let newBrightness = min(max(hsba.brightness + percentage, -1), 1) | ||
return UIColor(hue: hsba.hue, saturation: hsba.saturation, brightness: newBrightness, alpha: hsba.alpha) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import Foundation | ||
|
||
public struct UniformGradient: Gradient { | ||
|
||
public let colors: [UIColor] | ||
public let startPoint: CGPoint | ||
|
||
public init(colors: [UIColor], startPoint: CGPoint = CGPoint(x: 0.5, y: 0.0)) { | ||
self.colors = colors | ||
self.startPoint = startPoint | ||
} | ||
} | ||
|
||
public extension UniformGradient { | ||
|
||
func makeGradientComponents() -> [GradientComponents] { | ||
let min = 0.0 | ||
let max = 1.0 | ||
let by = (max-min)/Double(self.colors.count - 1) | ||
|
||
let locations = stride(from: min, through: max, by: by) | ||
.map { $0 } | ||
|
||
return zip(colors, locations) | ||
.map { GradientComponents(color: $0, location: $1) } | ||
} | ||
} |