Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e5b6e5caf9 | |||
| fee2df5cfd | |||
| 5726166d3d | |||
| 55f1893864 | |||
| bf388402fd | |||
| f814654106 | |||
| eeacb59a55 | |||
| ee5890b8ce | |||
| d116d7c380 | |||
| 2ec2d6f783 | |||
| 02dccb0804 | |||
| 74c2c3c8d7 | |||
| f9194ec712 |
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'KDCircularProgress'
|
||||
s.version = '1.3'
|
||||
s.version = '1.3.4'
|
||||
s.license = 'MIT'
|
||||
s.summary = 'A circular progress view with gradients written in Swift'
|
||||
s.homepage = 'https://github.com/kaandedeoglu/KDCircularProgress'
|
||||
|
||||
@@ -37,6 +37,28 @@ public class KDCircularProgress: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
static func InverseLerp(value: CGFloat, minMax: (CGFloat, CGFloat)) -> CGFloat {
|
||||
return (value - minMax.0) / (minMax.1 - minMax.0)
|
||||
}
|
||||
|
||||
static func Lerp(value: CGFloat, minMax: (CGFloat, CGFloat)) -> CGFloat {
|
||||
return (minMax.1 - minMax.0) * value + minMax.0
|
||||
}
|
||||
|
||||
static func ColorLerp(value: CGFloat, minMax: (UIColor, UIColor)) -> UIColor {
|
||||
let clampedValue = Clamp(value, minMax: (0, 1))
|
||||
|
||||
let zero: CGFloat = 0
|
||||
|
||||
var (r0, g0, b0, a0) = (zero, zero, zero, zero)
|
||||
minMax.0.getRed(&r0, green: &g0, blue: &b0, alpha: &a0)
|
||||
|
||||
var (r1, g1, b1, a1) = (zero, zero, zero, zero)
|
||||
minMax.1.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
|
||||
|
||||
return UIColor(red: Lerp(clampedValue, minMax: (r0, r1)), green: Lerp(clampedValue, minMax: (g0, g1)), blue: Lerp(clampedValue, minMax: (b0, b1)), alpha: Lerp(clampedValue, minMax: (a0, a1)))
|
||||
}
|
||||
|
||||
static func Mod(value: Int, range: Int, minMax: (Int, Int)) -> Int {
|
||||
let (min, max) = minMax
|
||||
assert(abs(range) <= abs(max - min), "range should be <= than the interval")
|
||||
@@ -91,6 +113,12 @@ public class KDCircularProgress: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
@IBInspectable public var lerpColorMode: Bool = false {
|
||||
didSet {
|
||||
progressLayer.lerpColorMode = lerpColorMode
|
||||
}
|
||||
}
|
||||
|
||||
@IBInspectable public var gradientRotateSpeed: CGFloat = 0 {
|
||||
didSet {
|
||||
progressLayer.gradientRotateSpeed = gradientRotateSpeed
|
||||
@@ -171,19 +199,19 @@ public class KDCircularProgress: UIView {
|
||||
self.init(frame: frame)
|
||||
setColors(colors)
|
||||
}
|
||||
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)!
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
userInteractionEnabled = false
|
||||
setInitialValues()
|
||||
super.init(coder: aDecoder)!
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
userInteractionEnabled = false
|
||||
setInitialValues()
|
||||
refreshValues()
|
||||
}
|
||||
}
|
||||
|
||||
public override func awakeFromNib() {
|
||||
checkAndSetIBColors()
|
||||
}
|
||||
|
||||
|
||||
override public class func layerClass() -> AnyClass {
|
||||
return KDCircularProgressViewLayer.self
|
||||
}
|
||||
@@ -204,6 +232,7 @@ public class KDCircularProgress: UIView {
|
||||
progressLayer.startAngle = UtilityFunctions.Mod(startAngle, range: 360, minMax: (0,360))
|
||||
progressLayer.clockwise = clockwise
|
||||
progressLayer.roundedCorners = roundedCorners
|
||||
progressLayer.lerpColorMode = lerpColorMode
|
||||
progressLayer.gradientRotateSpeed = gradientRotateSpeed
|
||||
progressLayer.glowAmount = UtilityFunctions.Clamp(glowAmount, minMax: (0, 1))
|
||||
progressLayer.glowMode = glowMode
|
||||
@@ -228,15 +257,24 @@ public class KDCircularProgress: UIView {
|
||||
progressLayer.setNeedsDisplay()
|
||||
}
|
||||
|
||||
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?) {
|
||||
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
|
||||
if isAnimating() {
|
||||
pauseAnimation()
|
||||
}
|
||||
|
||||
|
||||
let animationDuration: NSTimeInterval
|
||||
if relativeDuration {
|
||||
animationDuration = duration
|
||||
} else {
|
||||
let traveledAngle = UtilityFunctions.Mod(toAngle - fromAngle, range: 360, minMax: (0, 360))
|
||||
let scaledDuration = (NSTimeInterval(traveledAngle) * duration) / 360
|
||||
animationDuration = scaledDuration
|
||||
}
|
||||
|
||||
let animation = CABasicAnimation(keyPath: "angle")
|
||||
animation.fromValue = fromAngle
|
||||
animation.toValue = toAngle
|
||||
animation.duration = duration
|
||||
animation.duration = animationDuration
|
||||
animation.delegate = self
|
||||
angle = toAngle
|
||||
animationCompletionBlock = completion
|
||||
@@ -244,15 +282,15 @@ public class KDCircularProgress: UIView {
|
||||
progressLayer.addAnimation(animation, forKey: "angle")
|
||||
}
|
||||
|
||||
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?) {
|
||||
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
|
||||
if isAnimating() {
|
||||
pauseAnimation()
|
||||
}
|
||||
animateFromAngle(angle, toAngle: toAngle, duration: duration, completion: completion)
|
||||
animateFromAngle(angle, toAngle: toAngle, duration: duration, relativeDuration: relativeDuration, completion: completion)
|
||||
}
|
||||
|
||||
public func pauseAnimation() {
|
||||
let presentationLayer = progressLayer.presentationLayer() as! KDCircularProgressViewLayer
|
||||
guard let presentationLayer = progressLayer.presentationLayer() as? KDCircularProgressViewLayer else { return }
|
||||
let currentValue = presentationLayer.angle
|
||||
progressLayer.removeAllAnimations()
|
||||
animationCompletionBlock = nil
|
||||
@@ -310,6 +348,7 @@ public class KDCircularProgress: UIView {
|
||||
}
|
||||
}
|
||||
var roundedCorners: Bool!
|
||||
var lerpColorMode: Bool!
|
||||
var gradientRotateSpeed: CGFloat! {
|
||||
didSet {
|
||||
invalidateGradientCache()
|
||||
@@ -357,6 +396,7 @@ public class KDCircularProgress: UIView {
|
||||
startAngle = progressLayer.startAngle
|
||||
clockwise = progressLayer.clockwise
|
||||
roundedCorners = progressLayer.roundedCorners
|
||||
lerpColorMode = progressLayer.lerpColorMode
|
||||
gradientRotateSpeed = progressLayer.gradientRotateSpeed
|
||||
glowAmount = progressLayer.glowAmount
|
||||
glowMode = progressLayer.glowMode
|
||||
@@ -364,12 +404,13 @@ public class KDCircularProgress: UIView {
|
||||
trackThickness = progressLayer.trackThickness
|
||||
trackColor = progressLayer.trackColor
|
||||
colorsArray = progressLayer.colorsArray
|
||||
progressInsideFillColor = progressLayer.progressInsideFillColor
|
||||
}
|
||||
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
@@ -389,7 +430,7 @@ public class KDCircularProgress: UIView {
|
||||
CGContextSetLineWidth(ctx, trackLineWidth)
|
||||
CGContextSetLineCap(ctx, CGLineCap.Butt)
|
||||
CGContextDrawPath(ctx, .FillStroke)
|
||||
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
|
||||
let imageCtx = UIGraphicsGetCurrentContext()
|
||||
let reducedAngle = UtilityFunctions.Mod(angle, range: 360, minMax: (0, 360))
|
||||
@@ -411,7 +452,7 @@ public class KDCircularProgress: UIView {
|
||||
CGContextClipToMask(ctx, bounds, drawMask)
|
||||
|
||||
//Gradient - Fill
|
||||
if colorsArray.count > 1 {
|
||||
if !lerpColorMode && colorsArray.count > 1 {
|
||||
var componentsArray: [CGFloat] = []
|
||||
let rgbColorsArray: [UIColor] = colorsArray.map {c in // Make sure every color in colors array is in RGB color space
|
||||
if CGColorGetNumberOfComponents(c.CGColor) == 2 {
|
||||
@@ -429,11 +470,30 @@ public class KDCircularProgress: UIView {
|
||||
|
||||
drawGradientWithContext(ctx, componentsArray: componentsArray)
|
||||
} else {
|
||||
if colorsArray.count == 1 {
|
||||
fillRectWithContext(ctx, color: colorsArray[0])
|
||||
|
||||
var color: UIColor! = nil
|
||||
if colorsArray.count == 0 {
|
||||
color = UIColor.whiteColor()
|
||||
} else if colorsArray.count == 1 {
|
||||
color = colorsArray[0]
|
||||
} else {
|
||||
fillRectWithContext(ctx, color: UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0))
|
||||
|
||||
// lerpColorMode is true
|
||||
|
||||
let t = CGFloat(reducedAngle) / 360
|
||||
let steps = colorsArray.count - 1;
|
||||
let step = 1 / CGFloat(steps);
|
||||
for i in 1...steps {
|
||||
let fi = CGFloat(i)
|
||||
if (t <= fi * step || i == steps) {
|
||||
let colorT = UtilityFunctions.InverseLerp(t, minMax: ((fi - 1) * step, fi * step))
|
||||
color = UtilityFunctions.ColorLerp(colorT, minMax: (colorsArray[i - 1], colorsArray[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fillRectWithContext(ctx, color: color)
|
||||
}
|
||||
CGContextRestoreGState(ctx)
|
||||
UIGraphicsPopContext()
|
||||
@@ -448,7 +508,7 @@ public class KDCircularProgress: UIView {
|
||||
let baseSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let locations = locationsCache ?? gradientLocationsFromColorCount(componentsArray.count/4, gradientWidth: bounds.size.width)
|
||||
let gradient: CGGradient
|
||||
|
||||
|
||||
if let g = self.gradientCache {
|
||||
gradient = g
|
||||
} else {
|
||||
|
||||
@@ -8,8 +8,9 @@ Here's an example
|
||||
[Youtube Link](http://youtu.be/iIdas72MXOg)
|
||||
|
||||
|
||||
[](http://youtu.be/iIdas72MXOg)
|
||||

|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
@@ -33,7 +34,7 @@ view.addSubview(progress)
|
||||
```
|
||||
|
||||
## Installation
|
||||
- It's on Cocoapods under the name (you guessed it!) KDCircularProgress
|
||||
- It's on CocoaPods under the name (you guessed it!) KDCircularProgress
|
||||
- Just drag `KDCircularProgress.swift` into your project. `Carthage` support is on To-do list.
|
||||
|
||||
## Properties
|
||||
@@ -100,11 +101,13 @@ public func setColors(colors: UIColor...)
|
||||
Set the colors for the progress gradient.
|
||||
|
||||
```swift
|
||||
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?)
|
||||
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?)
|
||||
```
|
||||
|
||||
Animate the progress from an initial value to a final value, with a completion block that fires after the animation is done.
|
||||
|
||||
`relativeDuration` - specify if the duration is for the specific animation or is the duration that would make a full turn.
|
||||
|
||||
```swift
|
||||
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?)
|
||||
```
|
||||
@@ -129,7 +132,7 @@ Prefering light colors in the gradients gives better results. As mentioned befor
|
||||
##To-Do
|
||||
- [x] Add example project
|
||||
- [ ] Carthage Support
|
||||
- [x] Cocoapods Support
|
||||
- [x] CocoaPods Support
|
||||
- [x] IBDesignable/IBInspectable support
|
||||
- [ ] Adding a `progress` property as an alternative to `angle`
|
||||
- [ ] Clean up
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 861 KiB |
Reference in New Issue
Block a user