Last active
September 4, 2016 18:57
-
-
Save Calvin-Huang/fc9f600caf01bce4058ac88061c280a4 to your computer and use it in GitHub Desktop.
Change counting speed depends on cubic bezier calculate. https://github.com/Calvin-Huang/CHCountingLabel/blob/master/CHCountingLabel/CountingLabel.swift
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
import UIKit | |
import CHCubicBezier | |
class CountingLabel: UILabel { | |
var duration: Float = 0 | |
var easingControlPoints: (x1: Double, y1: Double, x2: Double, y2: Double)? { | |
didSet { | |
cubicBezier = CubicBezier(controlPoints: easingControlPoints!) | |
} | |
} | |
var easing: CubicBezier.Easing? { | |
didSet { | |
easingControlPoints = easing?.toControlPoints() | |
} | |
} | |
var isCounting: Bool = false | |
var isPause: Bool = false | |
var textFormatter: ((value: Double) -> String) = { value -> String in | |
return String(value) | |
} | |
var startValue: Double = 0 { | |
didSet { | |
startCountingValue = startValue | |
self.text = textFormatter(value: startValue) | |
} | |
} | |
var stopValue: Double = 0 | |
private var cubicBezier: CubicBezier? | |
private var timer: CADisplayLink? | |
private var startTimeStamp: Double = 0 | |
private var startCountingValue: Double = 0 | |
private var currentCountingValue: Double = 0 | |
convenience init(easing: CubicBezier.Easing, startValue: Double, stopValue: Double, frame: CGRect = CGRectZero) { | |
self.init(frame: frame) | |
self.startValue = startValue | |
self.stopValue = stopValue | |
self.easing = easing | |
} | |
convenience init(controlPoints: (Double, Double, Double, Double), startValue: Double, stopValue: Double, frame: CGRect = CGRectZero) { | |
self.init(frame: frame) | |
self.startValue = startValue | |
self.stopValue = stopValue | |
self.easingControlPoints = controlPoints | |
} | |
// MARK: - Initializers | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
self.initPropertiesDefaultValue() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
self.initPropertiesDefaultValue() | |
} | |
// MARK: - Selectors | |
func updateCountingLabel(_: AnyObject) { | |
guard let cubicBezier = cubicBezier else { | |
return | |
} | |
let duration: Double = (self.duration <= 0) ? fabs(stopValue - startCountingValue) : Double(self.duration) | |
// If duration is equal to zero, change time is stopValue reduce to startCountingValue means update text per seconds. | |
let changeTime = NSDate.timeIntervalSinceReferenceDate() - startTimeStamp | |
if changeTime >= duration { | |
timer?.invalidate() | |
timer = nil | |
} else { | |
let changeValue = stopValue - startCountingValue | |
let t = changeTime / duration | |
currentCountingValue = startCountingValue + changeValue * cubicBezier.easing(t) | |
self.text = textFormatter(value: currentCountingValue) | |
} | |
} | |
// MARK: - Public Methods | |
func start() { | |
if timer == nil { | |
startTimeStamp = NSDate.timeIntervalSinceReferenceDate() | |
if isPause { | |
startCountingValue = currentCountingValue | |
} | |
timer = CADisplayLink(target: self, selector: #selector(updateCountingLabel(_:))) | |
timer?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode) | |
isCounting = true | |
isPause = false | |
} | |
} | |
func pause() { | |
timer?.invalidate() | |
timer = nil | |
isCounting = false | |
isPause = true | |
} | |
func stop() { | |
pause() | |
isPause = false | |
startCountingValue = startValue | |
self.text = textFormatter(value: startValue) | |
} | |
// MARK: - Private Methods | |
private func initPropertiesDefaultValue() { | |
easing = .Linear | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment