環境
- Xcode 9.0 Build version 9A235
- Swift4
やりたいこと
数字が変化した時に、変化を分かりやすくするためアニメーションさせたい。
こんな感じ
実装方法
- CADisplayLinkを利用して画面描画毎に現在の値を表示するという方法で実装
- UILabelを継承した専用のクラスを実装。extensionで済ませたかったが、都度実行されるメソッドをselectorとして渡す必要があるため、各パラメータをプロパティにしてラベル自身に持たせて受け渡し
コード
class CountAnimationLabel: UILabel {
var startTime: CFTimeInterval!
var fromValue: Int!
var toValue: Int!
var duration: TimeInterval!
func animate(from fromValue: Int, to toValue: Int, duration: TimeInterval) {
text = "\(fromValue)"
// 開始時間を保存
self.startTime = CACurrentMediaTime()
self.fromValue = fromValue
self.toValue = toValue
self.duration = duration
// CADisplayLinkの生成
let link = CADisplayLink(target: self, selector: #selector(updateValue))
link.add(to: .current, forMode: .commonModes)
}
// 描画タイミング毎に呼ばれるメソッド
@objc func updateValue(link: CADisplayLink) {
// 開始からの進捗 0.0 〜 1.0くらい
let dt = (link.timestamp - self.startTime) / duration
// 終了時に最後の値を入れてCADisplayLinkを破棄
if dt >= 1.0 {
text = "\(toValue!)"
link.invalidate()
return
}
// 最初の値に進捗に応じた値を足して現在の値を計算
let current = Int(Double(toValue - fromValue) * dt) + fromValue
text = "\(current)"
}
}
追記
等幅フォントにするときれいにみえるよ!
github