表示される値がアニメーションしながら変わるUILabelを作ってみた


はじめに

アプリを作っていると

UILabelで表示される値がぱっと切り替わると機械的だなー

と感じる箇所がちょいちょい出てきました。

なめらかに変わったら見るの楽しくなるなー、変わってる感もわかりやすいなー

と、ふと思ったので、作ってみることにしました。

結果

変化方法等、諸々はご自由に変化していただくとして()

実装

まず実装を見せますぜ。


final class AnimateValueLabel: UILabel {

    private var loop         : CADisplayLink?
    private var startTime    : TimeInterval    = 0.0
    private var currentValue : Int             = 0
    private var newValue     : Int             = 0

    func setData(value: Int, animated: Bool = false) {
        self.newValue = value
        if animated && self.currentValue != self.newValue {
            self.animateValue()
        }
        else {
            self.currentValue = value
            self.setText(value: self.currentValue)
        }
    }

    private func animateValue() {
        self.startTime = Date.timeIntervalSinceReferenceDate
        self.loop      = CADisplayLink(target: self, selector: #selector(self.update))

        if #available(iOS 10.0, *) {
            self.loop?.preferredFramesPerSecond = 60
        }
        else {
            self.loop?.frameInterval = 1
        }

        self.loop?.add(to: .current, forMode: .common)
        self.loop?.isPaused = false
    }

    @objc
    private func update(displayLink: CADisplayLink) {
        let duration : TimeInterval = 0.3
        let elapsed  : TimeInterval = Date.timeIntervalSinceReferenceDate - self.startTime

        let progress: Int = Int(Easing.easeIn.quart.getProgress(elapsed: elapsed, duration: duration, startValue: CGFloat(self.currentValue), endValue: CGFloat(self.newValue)))

        self.setText(value: progress)

        if duration < elapsed {
            self.loop?.isPaused = true
            self.loop?.invalidate()
            self.currentValue = self.newValue
        }
    }

    private func setText(value: Int) {
        self.text = value
    }
}

CADisplayLinkやEasingに関しては過去記事を参考にしていただくとして、

https://qiita.com/haguhoms/items/c87d335756042bc867c4
https://qiita.com/haguhoms/items/abc5635e8fa95719cb12

これで、setDataに渡したvalueを、アニメーションしながら表示することに成功しました。

(コンマがついているのは、ここに書いたコードにはない機能です←)

最後に

もちろん、機械的が悪いとかそういう話では一切ありません。

し、全てがアニメーションすることが正しいわけでもないと思います。

が、抱いた不満や思いついたことを試してみて、体験価値的に良さげだったらプロダクトに導入する、そんな試みをひたすらやる旅も悪くないなって、つまりはそういうことです。