Skip to content

Commit

Permalink
Merge pull request #32 from f8th/master
Browse files Browse the repository at this point in the history
Added rate animations
  • Loading branch information
skywinder committed May 19, 2016
2 parents 8ba3644 + 1e2f2d7 commit 553f652
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 60 deletions.
7 changes: 2 additions & 5 deletions Example/Example/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="14F1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="ia3-CH-9hP">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="ia3-CH-9hP">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
Expand Down Expand Up @@ -121,7 +121,6 @@
<real key="value" value="20"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="isCircle" value="YES"/>
<userDefinedRuntimeAttribute type="boolean" keyPath="colorsArray" value="NO"/>
<userDefinedRuntimeAttribute type="number" keyPath="gaugeTypeInt">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
Expand Down Expand Up @@ -155,7 +154,6 @@
<userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
<real key="value" value="5"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="colorsArray" value="YES"/>
<userDefinedRuntimeAttribute type="number" keyPath="lineWidth">
<real key="value" value="22"/>
</userDefinedRuntimeAttribute>
Expand Down Expand Up @@ -187,7 +185,6 @@
<userDefinedRuntimeAttribute type="number" keyPath="lineWidth">
<real key="value" value="16"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="colorsArray" value="NO"/>
<userDefinedRuntimeAttribute type="number" keyPath="rotate">
<real key="value" value="0.0"/>
</userDefinedRuntimeAttribute>
Expand Down
23 changes: 6 additions & 17 deletions Example/Example/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class MainViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

gauge.colorsArray = [UIColor.redColor(), UIColor.orangeColor(), UIColor.yellowColor() ,UIColor.greenColor()]
}

@IBOutlet var allGauges: [Gauge]!
Expand All @@ -39,24 +39,13 @@ class MainViewController: UIViewController {
}

@IBAction func animateAction(sender: AnyObject) {
for gauge in self.allGauges {
let newRate : CGFloat = gauge.rate == 0.0 ? 10.0 : 0.0

// UIView.beginAnimations(nil, context: nil)
// UIView.setAnimationDuration(5.0)
// for gauge in self.allGauges {
// gauge.rate = gauge.rate == 0.0 ? 10 : 0
// }
// UIView.commitAnimations()
//
UIView.animateWithDuration(NSTimeInterval(5.0), animations: {
() -> Void in
print(self.allGauges.count)
for gauge in self.allGauges {
gauge.rate = gauge.rate == 0.0 ? 10 : 0
// gauge.rate = CGFloat(arc4random() % 10)
gauge.animateRate(5.0, newValue: newRate) { (finished) in
print("Gauge animation completed !")
}
return
})

}
}

@IBAction func switchChanged(sender: UISwitch) {
Expand Down
8 changes: 8 additions & 0 deletions GaugeKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
1C9405231B31D1BE001BF122 /* CAShapeLayer+oval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C94051F1B31D1BE001BF122 /* CAShapeLayer+oval.swift */; };
1C9405241B31D1BE001BF122 /* Gauge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C9405201B31D1BE001BF122 /* Gauge.swift */; };
1C9405251B31D1BE001BF122 /* GaugeCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C9405211B31D1BE001BF122 /* GaugeCircle.swift */; };
850835541CAE20BE001A0DDB /* UIColor+Blend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850835531CAE20BE001A0DDB /* UIColor+Blend.swift */; };
856D35181CACBE930007D5C6 /* Gauge+Animations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 856D35171CACBE930007D5C6 /* Gauge+Animations.swift */; };
D66F51CE3D9204261BCE1C87 /* GaugeLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66F53D8674BBD2D847BDB75 /* GaugeLine.swift */; };
/* End PBXBuildFile section */

Expand All @@ -38,6 +40,8 @@
1C94051F1B31D1BE001BF122 /* CAShapeLayer+oval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CAShapeLayer+oval.swift"; sourceTree = "<group>"; };
1C9405201B31D1BE001BF122 /* Gauge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Gauge.swift; sourceTree = "<group>"; };
1C9405211B31D1BE001BF122 /* GaugeCircle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GaugeCircle.swift; sourceTree = "<group>"; };
850835531CAE20BE001A0DDB /* UIColor+Blend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Blend.swift"; sourceTree = "<group>"; };
856D35171CACBE930007D5C6 /* Gauge+Animations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Gauge+Animations.swift"; sourceTree = "<group>"; };
D66F53D8674BBD2D847BDB75 /* GaugeLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GaugeLine.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -84,7 +88,9 @@
1C94051E1B31D1BE001BF122 /* GaugeHalf.swift */,
1C94051F1B31D1BE001BF122 /* CAShapeLayer+oval.swift */,
1C9405201B31D1BE001BF122 /* Gauge.swift */,
856D35171CACBE930007D5C6 /* Gauge+Animations.swift */,
1C9405211B31D1BE001BF122 /* GaugeCircle.swift */,
850835531CAE20BE001A0DDB /* UIColor+Blend.swift */,
1C9404D51B31CF85001BF122 /* GaugeKit.h */,
1C9404D31B31CF85001BF122 /* Supporting Files */,
D66F53D8674BBD2D847BDB75 /* GaugeLine.swift */,
Expand Down Expand Up @@ -227,7 +233,9 @@
buildActionMask = 2147483647;
files = (
1C9405221B31D1BE001BF122 /* GaugeHalf.swift in Sources */,
850835541CAE20BE001A0DDB /* UIColor+Blend.swift in Sources */,
1C9405231B31D1BE001BF122 /* CAShapeLayer+oval.swift in Sources */,
856D35181CACBE930007D5C6 /* Gauge+Animations.swift in Sources */,
1C9405241B31D1BE001BF122 /* Gauge.swift in Sources */,
1C9405251B31D1BE001BF122 /* GaugeCircle.swift in Sources */,
D66F51CE3D9204261BCE1C87 /* GaugeLine.swift in Sources */,
Expand Down
78 changes: 78 additions & 0 deletions GaugeKit/Gauge+Animations.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// Gauge+Animations.swift
// GaugeKit
//
// Created by David Pelletier on 16-03-30.
// Copyright © 2016 Petr Korolev. All rights reserved.
//

import UIKit

extension Gauge {
public func animateRate(duration: NSTimeInterval, newValue: CGFloat, completion: (Bool) -> ()) -> Void {
animationTimer.invalidate()

let refreshRate: Double = 0.1
let rateSpeed: CGFloat = CGFloat(refreshRate) * ((newValue - self.rate) / CGFloat(duration))
print(rateSpeed)

animationTimer = NSTimer.scheduledTimerWithTimeInterval(
refreshRate,
target: self,
selector: #selector(updateProgress),
userInfo: [newValue, rateSpeed],
repeats: true
)

animationTimer.fire()

animationCompletionBlock = completion
}

func updateProgress(let timer: NSTimer) -> Void {
let userInfo = timer.userInfo as! [CGFloat]
guard let newValue: CGFloat = userInfo.first! else {
print("GAUGE-KIT: Error, new value not defined...")
return
}

guard let rateSpeed: CGFloat = userInfo.last else {
print("GAUGE-KIT: Error, rate speed could not be defined...")
return
}

self.rate += rateSpeed

if rateSpeed < 0 {
if self.rate <= newValue {
self.rate = newValue
timer.invalidate()
animationCompletionBlock(true)
//print("GAUGE-KIT: Gauge went down to \(newValue)")
}

if self.rate <= 0 {
self.rate = 0
timer.invalidate()
animationCompletionBlock(true)
//print("GAUGE-KIT: Gauge emptied")
}
}

if rateSpeed >= 0 {
if self.rate >= newValue {
self.rate = newValue
timer.invalidate()
animationCompletionBlock(true)
//print("GAUGE-KIT: Gauge went up to \(newValue)")
}

if self.rate >= self.maxValue {
self.rate = self.maxValue
timer.invalidate()
animationCompletionBlock(true)
//print("GAUGE-KIT: Gauge filled")
}
}
}
}
73 changes: 35 additions & 38 deletions GaugeKit/Gauge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public enum GaugeType: Int {

@IBDesignable
public class Gauge: UIView {

@IBInspectable public var startColor: UIColor = UIColor.greenColor() {
didSet {
resetLayers()
Expand Down Expand Up @@ -82,7 +81,7 @@ public class Gauge: UIView {
updateLayerProperties()
}
}
@IBInspectable public var colorsArray: Bool = false {
@IBInspectable public var colorsArray: [UIColor] = [] {
didSet {
updateLayerProperties()
}
Expand Down Expand Up @@ -169,6 +168,10 @@ public class Gauge: UIView {
/// background gradient
var bgGradientLayer: CAGradientLayer!

// Animation variables
internal var animationTimer: NSTimer = NSTimer()
internal var animationCompletionBlock: (Bool) -> () = {_ in }

func getGauge(rotateAngle: Double = 0) -> CAShapeLayer {
switch type {
case .Left, .Right:
Expand All @@ -184,54 +187,50 @@ public class Gauge: UIView {

func updateLayerProperties() {
backgroundColor = UIColor.clearColor()

if (ringLayer != nil) {

switch (type) {
switch type {
case .Left, .Right:
// For Half gauge you have to fill 50% of circle and round it wisely.
let percanage = rate / 2 / maxValue % 0.5
ringLayer.strokeEnd = (rate >= maxValue ? 0.5 : percanage + ((rate != 0 && percanage == 0) ? 0.5 : 0))
case .Circle, .Custom:
ringLayer.strokeEnd = rate / maxValue
// For Half Gauge, you have to fill 50% of circle and round it wisely
let percentage = rate / 2 / maxValue % 0.5
ringLayer.strokeEnd = (rate >= maxValue ? 0.5 : percentage + ((rate != 0 && percentage == 0) ? 0.5 : 0))
default:
ringLayer.strokeEnd = rate / maxValue

}

var strokeColor = UIColor.lightGrayColor()
//TODO: replace pre-defined colors with array of user-defined colors
//TODO: and split them proportionally in whole sector
if colorsArray {
switch (rate / maxValue) {
case let r where r >= 0.75:
strokeColor = UIColor(hue:
112.0 / 360.0, saturation:
0.39, brightness: 0.85,
alpha: 1.0)
case let r where r >= 0.5:
strokeColor = UIColor(hue:
208.0 / 360.0, saturation:
0.51, brightness: 0.75,
alpha: 1.0)
case let r where r >= 0.25:
strokeColor = UIColor(hue: 40.0 / 360.0, saturation: 0.39,
brightness: 0.85, alpha: 1.0)

if !colorsArray.isEmpty {
switch colorsArray.count {
case 1:
strokeColor = colorsArray.first!
case 2:
let percentage: CGFloat = rate / maxValue
strokeColor = (1 - percentage) * colorsArray.first! + percentage * colorsArray.last!
default:
strokeColor = UIColor(hue:
359.0 / 360.0, saturation:
0.48, brightness: 0.63,
alpha: 1.0)
let percentageInSector: CGFloat = (rate / maxValue * CGFloat(colorsArray.count - 1) * 100.0 % 100.0) / 100.0
let currentSector: Int = Int(rate / maxValue * CGFloat(colorsArray.count - 1)) + 1
//print(currentSector)
//print(percentageInSector)

let firstColor = colorsArray[currentSector - 1]
let secondColor = colorsArray[min(currentSector, colorsArray.count - 1)]

strokeColor = (1.0 - percentageInSector) * firstColor + percentageInSector * secondColor
}
if (ringGradientLayer != nil) {

if type == .Line {
ringLayer.strokeColor = strokeColor.CGColor
}

if ringGradientLayer != nil {
ringGradientLayer.colors = [strokeColor.CGColor, strokeColor.CGColor]
} else {
ringLayer.strokeColor = strokeColor.CGColor
}
} else {
ringLayer.strokeColor = startColor.CGColor
}

}
}

Expand Down Expand Up @@ -276,6 +275,4 @@ public class Gauge: UIView {
layer.addSublayer(gaugeLayer)
updateLayerProperties()
}
}


}
41 changes: 41 additions & 0 deletions GaugeKit/UIColor+Blend.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// UIColor+Blend.swift
// SWGauge
//
// Created by David Pelletier on 2015-03-06.
// Copyright (c) 2015 Petr Korolev. All rights reserved.
//

import UIKit

func + (left: UIColor, right: UIColor) -> UIColor {
var leftRGBA = [CGFloat](count: 4, repeatedValue: 0.0)
var rightRGBA = [CGFloat](count: 4, repeatedValue: 0.0)

left.getRed(&leftRGBA[0], green: &leftRGBA[1], blue: &leftRGBA[2], alpha: &leftRGBA[3])
right.getRed(&rightRGBA[0], green: &rightRGBA[1], blue: &rightRGBA[2], alpha: &rightRGBA[3])

return UIColor(
red: max(leftRGBA[0], rightRGBA[0]),
green: max(leftRGBA[1], rightRGBA[1]),
blue: max(leftRGBA[2], rightRGBA[2]),
alpha: max(leftRGBA[3], rightRGBA[3])
)
}

func * (left: CGFloat, right: UIColor) -> UIColor {
var rightRGBA = [CGFloat](count: 4, repeatedValue: 0.0)

right.getRed(&rightRGBA[0], green: &rightRGBA[1], blue: &rightRGBA[2], alpha: &rightRGBA[3])

return UIColor(
red: rightRGBA[0] * left,
green: rightRGBA[1] * left,
blue: rightRGBA[2] * left,
alpha: rightRGBA[3]
)
}

func * (left: UIColor, right: CGFloat) -> UIColor {
return right * left
}

0 comments on commit 553f652

Please sign in to comment.