31 Commits

Author SHA1 Message Date
Kaan Dedeoglu fb5f616d82 Merge pull request #39 from pakmee/swift2.3
converted to swift 2.3 and fixed auto correct with context
2016-09-06 18:50:21 +03:00
Jonathan Siao aa4edacabf cleaned spaces 2016-09-05 14:09:57 +04:00
Jonathan Siao 6475bc0a58 converted to swift 2.3 and fixed auto correct with context 2016-09-05 14:02:15 +04:00
Kaan Dedeoglu edeba04ff9 Merge pull request #36 from Morbix/patch-3
Update README.md
2016-07-26 14:07:14 +03:00
Kaan Dedeoglu f185b1f33d Merge pull request #34 from Morbix/patch-1
Adding CocoaPods badges
2016-07-26 14:06:58 +03:00
Henrique Morbin 79bf0d3457 Update README.md
Fix
2016-07-25 20:51:16 -03:00
Kaan Dedeoglu 4f2cfc1687 Merge pull request #35 from Morbix/patch-2
Update README.md
2016-07-26 01:11:40 +03:00
Henrique Morbin 174357710b Update README.md 2016-07-25 17:06:51 -03:00
Henrique Morbin f10c403fc2 Adding CocoaPods badges 2016-07-25 17:04:05 -03:00
Kaan Dedeoglu 094a5a64e5 bump version to 1.4.1 2016-07-21 12:36:01 +03:00
Kaan Dedeoglu 3c38489154 clear the current completionBlock variable before calling it. fixes #31 2016-07-21 12:35:08 +03:00
Kaan Dedeoglu 1d9ab519f1 Merge pull request #26 from stevekim0417/master
Master
2016-06-23 17:56:26 +03:00
Macbook 60d95709c7 Merge remote-tracking branch 'kaandedeoglu/master' 2016-06-23 23:49:16 +09:00
Macbook 0e95379f6d flag
It is not called the completion block after doing cancel.
2016-06-23 23:44:18 +09:00
Kaan Dedeoglu 840ae1fcbc Clean up and refactoring 2016-06-21 00:29:41 +03:00
Steve Kim 36160ed532 issue : not calling completion block after doing cancel
It works fine after doing cancel.
2016-05-29 16:04:06 +09:00
Kaan Dedeoglu d96c0a95a3 Merge pull request #19 from aborren/master
Changed angle to Double instead of Int
2016-04-06 14:04:03 +03:00
Dan Isacson e9d2ffa247 update podspec to 1.4.0 2016-04-04 14:35:55 +02:00
Dan Isacson 0b46df2ce7 Changed angle to use Double instead of Int. This change was made in order to make slow animations smoother. 2016-04-04 13:30:47 +02:00
Kaan Dedeoglu e5b6e5caf9 Avoid var parameters - which will be deprecated with Swift 3.0 2016-03-28 00:25:51 +03:00
Kaan Dedeoglu fee2df5cfd Update Podspec to 1.3.4 2016-03-27 13:46:21 +03:00
Kaan Dedeoglu 5726166d3d Merge pull request #18 from maltalef/master
Added colorLerpMode
2016-03-27 13:45:05 +03:00
Matias Altalef 55f1893864 Added colorLerpMode (default false): when true, it's filled with a solid color that changes with progress (only if there's more than one) 2016-03-26 18:02:19 -03:00
Kaan Dedeoglu bf388402fd Merge pull request #17 from ReadmeCritic/master
Correct the spelling of CocoaPods in README
2016-02-12 21:22:31 +02:00
ReadmeCritic f814654106 Correct the spelling of CocoaPods in README 2016-02-12 11:17:11 -08:00
Kaan Dedeoglu eeacb59a55 Make sure the presentationLayer is non-nil before trying to pause animations. Update to version 1.3.3 2016-01-27 12:07:46 +02:00
Kaan Dedeoglu ee5890b8ce Update Podspec to 1.3.2 2016-01-10 11:37:53 +02:00
Kaan Dedeoglu d116d7c380 Fix bug related to animations with progressInsideFillColor. Fix indentation 2016-01-10 11:34:56 +02:00
Kaan Dedeoglu 2ec2d6f783 Add gif to README 2015-11-12 14:39:40 +02:00
Kaan Dedeoglu 02dccb0804 Update podspec to 1.3.1 2015-11-11 13:57:45 +02:00
Kaan Dedeoglu 74c2c3c8d7 Update README.md 2015-11-11 13:56:37 +02:00
6 changed files with 196 additions and 101 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KDCircularProgress'
s.version = '1.3'
s.version = '1.4.1'
s.license = 'MIT'
s.summary = 'A circular progress view with gradients written in Swift'
s.homepage = 'https://github.com/kaandedeoglu/KDCircularProgress'
+158 -94
View File
@@ -13,20 +13,20 @@ public enum KDCircularProgressGlowMode {
}
@IBDesignable
public class KDCircularProgress: UIView {
public class KDCircularProgress: UIView,CAAnimationDelegate {
private struct ConversionFunctions {
static func DegreesToRadians (value:CGFloat) -> CGFloat {
private struct Conversion {
static func degreesToRadians (value:CGFloat) -> CGFloat {
return value * CGFloat(M_PI) / 180.0
}
static func RadiansToDegrees (value:CGFloat) -> CGFloat {
static func radiansToDegrees (value:CGFloat) -> CGFloat {
return value * 180.0 / CGFloat(M_PI)
}
}
private struct UtilityFunctions {
static func Clamp<T: Comparable>(value: T, minMax: (T, T)) -> T {
private struct Utility {
static func clamp<T: Comparable>(value: T, minMax: (T, T)) -> T {
let (min, max) = minMax
if value < min {
return min
@@ -37,20 +37,42 @@ public class KDCircularProgress: UIView {
}
}
static func Mod(value: Int, range: Int, minMax: (Int, Int)) -> Int {
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: Double, range: Double, minMax: (Double, Double)) -> Double {
let (min, max) = minMax
assert(abs(range) <= abs(max - min), "range should be <= than the interval")
if value >= min && value <= max {
return value
} else if value < min {
return Mod(value + range, range: range, minMax: minMax)
return mod(value + range, range: range, minMax: minMax)
} else {
return Mod(value - range, range: range, minMax: minMax)
return mod(value - range, range: range, minMax: minMax)
}
}
}
private var progressLayer: KDCircularProgressViewLayer! {
private var progressLayer: KDCircularProgressViewLayer {
get {
return layer as! KDCircularProgressViewLayer
}
@@ -62,7 +84,7 @@ public class KDCircularProgress: UIView {
}
}
@IBInspectable public var angle: Int = 0 {
@IBInspectable public var angle: Double = 0 {
didSet {
if self.isAnimating() {
self.pauseAnimation()
@@ -71,9 +93,10 @@ public class KDCircularProgress: UIView {
}
}
@IBInspectable public var startAngle: Int = 0 {
@IBInspectable public var startAngle: Double = 0 {
didSet {
progressLayer.startAngle = UtilityFunctions.Mod(startAngle, range: 360, minMax: (0,360))
startAngle = Utility.mod(startAngle, range: 360, minMax: (0, 360))
progressLayer.startAngle = startAngle
progressLayer.setNeedsDisplay()
}
}
@@ -91,6 +114,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
@@ -99,7 +128,8 @@ public class KDCircularProgress: UIView {
@IBInspectable public var glowAmount: CGFloat = 1.0 {//Between 0 and 1
didSet {
progressLayer.glowAmount = UtilityFunctions.Clamp(glowAmount, minMax: (0, 1))
glowAmount = Utility.clamp(glowAmount, minMax: (0, 1))
progressLayer.glowAmount = glowAmount
}
}
@@ -111,19 +141,19 @@ public class KDCircularProgress: UIView {
@IBInspectable public var progressThickness: CGFloat = 0.4 {//Between 0 and 1
didSet {
progressThickness = UtilityFunctions.Clamp(progressThickness, minMax: (0, 1))
progressThickness = Utility.clamp(progressThickness, minMax: (0, 1))
progressLayer.progressThickness = progressThickness/2
}
}
@IBInspectable public var trackThickness: CGFloat = 0.5 {//Between 0 and 1
didSet {
trackThickness = UtilityFunctions.Clamp(trackThickness, minMax: (0, 1))
trackThickness = Utility.clamp(trackThickness, minMax: (0, 1))
progressLayer.trackThickness = trackThickness/2
}
}
@IBInspectable public var trackColor: UIColor = UIColor.blackColor() {
@IBInspectable public var trackColor: UIColor = .blackColor() {
didSet {
progressLayer.trackColor = trackColor
progressLayer.setNeedsDisplay()
@@ -135,7 +165,7 @@ public class KDCircularProgress: UIView {
if let color = progressInsideFillColor {
progressLayer.progressInsideFillColor = color
} else {
progressLayer.progressInsideFillColor = UIColor.clearColor()
progressLayer.progressInsideFillColor = .clearColor()
}
}
}
@@ -156,7 +186,6 @@ public class KDCircularProgress: UIView {
@objc @IBInspectable private var IBColor2: UIColor?
@objc @IBInspectable private var IBColor3: UIColor?
private var animationCompletionBlock: ((Bool) -> Void)?
override public init(frame: CGRect) {
@@ -171,19 +200,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
}
@@ -196,16 +225,17 @@ public class KDCircularProgress: UIView {
private func setInitialValues() {
radius = (frame.size.width/2.0) * 0.8 //We always apply a 20% padding, stopping glows from being clipped
backgroundColor = .clearColor()
setColors(UIColor.whiteColor(), UIColor.redColor())
setColors(.whiteColor(), .cyanColor())
}
private func refreshValues() {
progressLayer.angle = angle
progressLayer.startAngle = UtilityFunctions.Mod(startAngle, range: 360, minMax: (0,360))
progressLayer.startAngle = startAngle
progressLayer.clockwise = clockwise
progressLayer.roundedCorners = roundedCorners
progressLayer.lerpColorMode = lerpColorMode
progressLayer.gradientRotateSpeed = gradientRotateSpeed
progressLayer.glowAmount = UtilityFunctions.Clamp(glowAmount, minMax: (0, 1))
progressLayer.glowAmount = glowAmount
progressLayer.glowMode = glowMode
progressLayer.progressThickness = progressThickness/2
progressLayer.trackColor = trackColor
@@ -213,8 +243,8 @@ public class KDCircularProgress: UIView {
}
private func checkAndSetIBColors() {
let nonNilColors = [IBColor1, IBColor2, IBColor3].filter { $0 != nil}.map { $0! }
if nonNilColors.count > 0 {
let nonNilColors = [IBColor1, IBColor2, IBColor3].flatMap { $0 }
if !nonNilColors.isEmpty {
setColors(nonNilColors)
}
}
@@ -228,20 +258,20 @@ public class KDCircularProgress: UIView {
progressLayer.setNeedsDisplay()
}
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
public func animateFromAngle(fromAngle: Double, toAngle: Double, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
if isAnimating() {
pauseAnimation()
}
let animationDuration: NSTimeInterval
if relativeDuration {
animationDuration = duration
animationDuration = duration
} else {
let traveledAngle = UtilityFunctions.Mod(toAngle - fromAngle, range: 360, minMax: (0, 360))
let traveledAngle = Utility.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
@@ -253,7 +283,7 @@ public class KDCircularProgress: UIView {
progressLayer.addAnimation(animation, forKey: "angle")
}
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
public func animateToAngle(toAngle: Double, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
if isAnimating() {
pauseAnimation()
}
@@ -261,7 +291,7 @@ public class KDCircularProgress: UIView {
}
public func pauseAnimation() {
let presentationLayer = progressLayer.presentationLayer() as! KDCircularProgressViewLayer
guard let presentationLayer = progressLayer.presentationLayer() else { return }
let currentValue = presentationLayer.angle
progressLayer.removeAllAnimations()
animationCompletionBlock = nil
@@ -269,6 +299,7 @@ public class KDCircularProgress: UIView {
}
public func stopAnimation() {
animationCompletionBlock = nil
progressLayer.removeAllAnimations()
angle = 0
}
@@ -277,10 +308,13 @@ public class KDCircularProgress: UIView {
return progressLayer.animationForKey("angle") != nil
}
override public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if let completionBlock = animationCompletionBlock {
if flag {
animationCompletionBlock = nil
}
completionBlock(flag)
animationCompletionBlock = nil
}
}
@@ -304,13 +338,13 @@ public class KDCircularProgress: UIView {
}
private class KDCircularProgressViewLayer: CALayer {
@NSManaged var angle: Int
@NSManaged var angle: Double
var radius: CGFloat! {
didSet {
invalidateGradientCache()
}
}
var startAngle: Int!
var startAngle: Double!
var clockwise: Bool! {
didSet {
if clockwise != oldValue {
@@ -319,6 +353,7 @@ public class KDCircularProgress: UIView {
}
}
var roundedCorners: Bool!
var lerpColorMode: Bool!
var gradientRotateSpeed: CGFloat! {
didSet {
invalidateGradientCache()
@@ -340,7 +375,7 @@ public class KDCircularProgress: UIView {
private struct GlowConstants {
private static let sizeToGlowRatio: CGFloat = 0.00015
static func glowAmountForAngle(angle: Int, glowAmount: CGFloat, glowMode: KDCircularProgressGlowMode, size: CGFloat) -> CGFloat {
static func glowAmountForAngle(angle: Double, glowAmount: CGFloat, glowMode: KDCircularProgressGlowMode, size: CGFloat) -> CGFloat {
switch glowMode {
case .Forward:
return CGFloat(angle) * size * sizeToGlowRatio * glowAmount
@@ -366,6 +401,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
@@ -373,75 +409,104 @@ 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)
}
override func drawInContext(ctx: CGContext) {
UIGraphicsPushContext(ctx)
let rect = bounds
let size = rect.size
let trackLineWidth: CGFloat = radius * trackThickness
let size = bounds.size
let width = size.width
let height = size.height
let trackLineWidth = radius * trackThickness
let progressLineWidth = radius * progressThickness
let arcRadius = max(radius - trackLineWidth/2, radius - progressLineWidth/2)
CGContextAddArc(ctx, CGFloat(size.width/2.0), CGFloat(size.height/2.0), arcRadius, 0, CGFloat(M_PI * 2), 0)
CGContextAddArc(ctx, width/2.0, height/2.0, arcRadius, 0, CGFloat(M_PI * 2), 0)
trackColor.set()
CGContextSetStrokeColorWithColor(ctx, trackColor.CGColor)
CGContextSetFillColorWithColor(ctx, progressInsideFillColor.CGColor)
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))
let fromAngle = ConversionFunctions.DegreesToRadians(CGFloat(-startAngle))
let toAngle = ConversionFunctions.DegreesToRadians(CGFloat((clockwise == true ? -reducedAngle : reducedAngle) - startAngle))
CGContextAddArc(imageCtx, CGFloat(size.width/2.0),CGFloat(size.height/2.0), arcRadius, fromAngle, toAngle, clockwise == true ? 1 : 0)
let glowValue = GlowConstants.glowAmountForAngle(reducedAngle, glowAmount: glowAmount, glowMode: glowMode, size: size.width)
if glowValue > 0 {
CGContextSetShadowWithColor(imageCtx, CGSizeZero, glowValue, UIColor.blackColor().CGColor)
let reducedAngle = Utility.mod(angle, range: 360, minMax: (0, 360))
if let imageCtx = UIGraphicsGetCurrentContext(){
let fromAngle = Conversion.degreesToRadians(CGFloat(-startAngle))
let toAngle = Conversion.degreesToRadians(CGFloat((clockwise == true ? -reducedAngle : reducedAngle) - startAngle))
CGContextAddArc(imageCtx, width/2.0, height/2.0, arcRadius, fromAngle, toAngle, clockwise == true ? 1 : 0)
let glowValue = GlowConstants.glowAmountForAngle(reducedAngle, glowAmount: glowAmount, glowMode: glowMode, size: width)
if glowValue > 0 {
CGContextSetShadowWithColor(imageCtx, CGSizeZero, glowValue, UIColor.blackColor().CGColor)
}
CGContextSetLineCap(imageCtx, roundedCorners == true ? .Round : .Butt)
CGContextSetLineWidth(imageCtx, progressLineWidth)
CGContextDrawPath(imageCtx, .Stroke)
guard let currentGraphicsContext = UIGraphicsGetCurrentContext() else{
return
}
if let drawMask: CGImageRef = CGBitmapContextCreateImage(currentGraphicsContext){
UIGraphicsEndImageContext()
CGContextSaveGState(ctx)
CGContextClipToMask(ctx, bounds, drawMask)
}else{
UIGraphicsEndImageContext()
}
}
CGContextSetLineCap(imageCtx, roundedCorners == true ? .Round : .Butt)
CGContextSetLineWidth(imageCtx, progressLineWidth)
CGContextDrawPath(imageCtx, .Stroke)
let drawMask: CGImageRef = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext())!
UIGraphicsEndImageContext()
CGContextSaveGState(ctx)
CGContextClipToMask(ctx, bounds, drawMask)
//Gradient - Fill
if 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 {
let whiteValue = CGColorGetComponents(c.CGColor)[0]
if !lerpColorMode && colorsArray.count > 1 {
let rgbColorsArray: [UIColor] = colorsArray.map { color in // Make sure every color in colors array is in RGB color space
if CGColorGetNumberOfComponents(color.CGColor) == 2 {
let whiteValue = CGColorGetComponents(color.CGColor)[0]
return UIColor(red: whiteValue, green: whiteValue, blue: whiteValue, alpha: 1.0)
} else {
return c
return color
}
}
for color in rgbColorsArray {
let colorComponents: UnsafePointer<CGFloat> = CGColorGetComponents(color.CGColor)
componentsArray.appendContentsOf([colorComponents[0],colorComponents[1],colorComponents[2],1.0])
let componentsArray = rgbColorsArray.flatMap { color -> [CGFloat] in
let components: UnsafePointer<CGFloat> = CGColorGetComponents(color.CGColor)
return [components[0], components[1], components[2], 1.0]
}
drawGradientWithContext(ctx, componentsArray: componentsArray)
} else {
if colorsArray.count == 1 {
fillRectWithContext(ctx, color: colorsArray[0])
var color: UIColor?
if colorsArray.isEmpty {
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 = Utility.inverseLerp(t, minMax: ((fi - 1) * step, fi * step))
color = Utility.colorLerp(colorT, minMax: (colorsArray[i - 1], colorsArray[i]))
break
}
}
}
if let color = color {
fillRectWithContext(ctx, color: color)
}
}
CGContextRestoreGState(ctx)
@@ -455,21 +520,24 @@ public class KDCircularProgress: UIView {
private func drawGradientWithContext(ctx: CGContext!, componentsArray: [CGFloat]) {
let baseSpace = CGColorSpaceCreateDeviceRGB()
let locations = locationsCache ?? gradientLocationsFromColorCount(componentsArray.count/4, gradientWidth: bounds.size.width)
let locations = locationsCache ?? gradientLocationsForColorCount(componentsArray.count/4, gradientWidth: bounds.size.width)
let gradient: CGGradient
if let g = self.gradientCache {
gradient = g
if let cachedGradient = gradientCache {
gradient = cachedGradient
} else {
guard let g = CGGradientCreateWithColorComponents(baseSpace, componentsArray, locations,componentsArray.count / 4) else { return }
self.gradientCache = g
gradient = g
guard let cachedGradient = CGGradientCreateWithColorComponents(baseSpace, componentsArray, locations,componentsArray.count / 4) else {
return
}
gradientCache = cachedGradient
gradient = cachedGradient
}
let halfX = bounds.size.width/2.0
let halfX = bounds.size.width / 2.0
let floatPi = CGFloat(M_PI)
let rotateSpeed = clockwise == true ? gradientRotateSpeed : gradientRotateSpeed * -1
let angleInRadians = ConversionFunctions.DegreesToRadians(rotateSpeed * CGFloat(angle) - 90)
let angleInRadians = Conversion.degreesToRadians(rotateSpeed * CGFloat(angle) - 90)
let oppositeAngle = angleInRadians > floatPi ? angleInRadians - floatPi : angleInRadians + floatPi
let startPoint = CGPoint(x: (cos(angleInRadians) * halfX) + halfX, y: (sin(angleInRadians) * halfX) + halfX)
@@ -478,19 +546,15 @@ public class KDCircularProgress: UIView {
CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, .DrawsBeforeStartLocation)
}
private func gradientLocationsFromColorCount(colorCount: Int, gradientWidth: CGFloat) -> [CGFloat] {
private func gradientLocationsForColorCount(colorCount: Int, gradientWidth: CGFloat) -> [CGFloat] {
if colorCount == 0 || gradientWidth == 0 {
return []
} else {
var locationsArray: [CGFloat] = []
let progressLineWidth = radius * progressThickness
let firstPoint = gradientWidth/2 - (radius - progressLineWidth/2)
let increment = (gradientWidth - (2*firstPoint))/CGFloat(colorCount - 1)
for i in 0..<colorCount {
locationsArray.append(firstPoint + (CGFloat(i) * increment))
}
assert(locationsArray.count == colorCount, "color counts should be equal")
let locationsArray = (0..<colorCount).map { firstPoint + (CGFloat($0) * increment) }
let result = locationsArray.map { $0 / gradientWidth }
locationsCache = result
return result
@@ -174,9 +174,11 @@
TargetAttributes = {
BC9E75851A8CE4A500B1DF3D = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0800;
};
BC9E759A1A8CE4A500B1DF3D = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0800;
TestTargetID = BC9E75851A8CE4A500B1DF3D;
};
};
@@ -353,6 +355,7 @@
INFOPLIST_FILE = KDCircularProgressExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
};
name = Debug;
};
@@ -363,6 +366,7 @@
INFOPLIST_FILE = KDCircularProgressExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
};
name = Release;
};
@@ -381,6 +385,7 @@
INFOPLIST_FILE = KDCircularProgressExampleTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KDCircularProgressExample.app/KDCircularProgressExample";
};
name = Debug;
@@ -396,6 +401,7 @@
INFOPLIST_FILE = KDCircularProgressExampleTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KDCircularProgressExample.app/KDCircularProgressExample";
};
name = Release;
@@ -9,7 +9,6 @@
import UIKit
class ViewController: UIViewController {
var progress: KDCircularProgress!
override func viewDidLoad() {
@@ -31,7 +30,7 @@ class ViewController: UIViewController {
}
@IBAction func sliderDidChangeValue(sender: UISlider) {
progress.angle = Int(sender.value)
progress.angle = Double(sender.value)
}
@IBAction func animateButtonTapped(sender: UIButton) {
+30 -4
View File
@@ -1,4 +1,9 @@
# KDCircularProgress
[![Version](https://img.shields.io/cocoapods/v/KDCircularProgress.svg?style=flat)](http://cocoapods.org/pods/KDCircularProgress)
[![License](https://img.shields.io/cocoapods/l/KDCircularProgress.svg?style=flat)](http://cocoapods.org/pods/KDCircularProgress)
[![Platform](https://img.shields.io/cocoapods/p/KDCircularProgress.svg?style=flat)](http://cocoapods.org/pods/KDCircularProgress)
`KDCircularProgress` is a circular progress view written in Swift. It makes it possible to have gradients in the progress view, along with glows and animations.
KDCircularProgress also has `IBInspectable` and `IBDesignable` support, so you can configure and preview inside the `Interface Builder`.
@@ -8,8 +13,9 @@ Here's an example
[Youtube Link](http://youtu.be/iIdas72MXOg)
[![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot.png)](http://youtu.be/iIdas72MXOg)
![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot.gif)
![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot.png)
![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot2.jpg)
![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot3.jpg)
![Screenshot](https://raw.githubusercontent.com/kaandedeoglu/KDCircularProgress/master/screenshot4.jpg)
@@ -33,9 +39,27 @@ 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.
### CocoaPods
KDCircularProgress is available through [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod 'KDCircularProgress'
```
### Manually
Just drag `KDCircularProgress.swift` into your project.
### Carthage
`Carthage` support is on To-do list.
## Properties
####progressColors: `[UIColor]`
@@ -100,11 +124,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 +155,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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB