LoginSignup
11
12

More than 5 years have passed since last update.

UILabelでエレベーター風なアニメーション

Posted at

はじめに

ラベルの数字がエレベーター風に昇降アニメーションする実装をしてみました。
完成イメージは下のような感じ↓

Untitled.gif

環境

  • XCode7.2 (swift2.1)

実装

アニメーションするラベル

primaryLabelsecondaryLabelの2つのラベルを用意して、originをアニメーションさせていきます。

PMElevateLabel.swift
import UIKit

class PMElevateLabel: UIView {

    //MARK: - Properties
    //MARK: Public
    var duration : NSTimeInterval = 1.0

    //MARK: Private
    private var currentValue : Int = 0
    private var primaryLabel : UILabel!
    private var secondaryLabel : UILabel!

    //MARK: - Initializer
    override init(frame: CGRect) {
        super.init(frame: frame)

        self.layer.masksToBounds = true

        primaryLabel = self.label(CGRectMake(0, 0, frame.width, frame.height))
        self.addSubview(primaryLabel)

        secondaryLabel = self.label(CGRectMake(0, 0, frame.width, frame.height))
        self.addSubview(secondaryLabel)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    //MARK: - Public method
    func setValue(value : Int, animated : Bool) {
        if self.currentValue == value {
            return
        }

        self.primaryLabel.text = "\(self.currentValue)"
        self.secondaryLabel.text = "\(value)"

        let destOffset = (self.currentValue > value) ? -self.frame.height : self.frame.height

        self.primaryLabel.setOrigin(.zero)
        self.secondaryLabel.setOrigin(CGPointMake(0, destOffset))

        UIView.animateWithDuration((animated) ? self.duration : 0.0, delay: 0.0, options: .CurveLinear, animations: { () -> Void in
            self.primaryLabel.setOrigin(CGPointMake(0, -destOffset))
            self.secondaryLabel.setOrigin(.zero)
            }, completion: { _ in })

        self.currentValue = value
    }

    //MARK: - Private method
    private func label(frame : CGRect) -> UILabel {
        let label = UILabel(frame: frame)
        label.backgroundColor = UIColor.clearColor()
        label.textAlignment = .Center
        label.font = UIFont.systemFontOfSize(50)
        return label
    }
}

extension UIView {
    func setOrigin(origin : CGPoint) {
        var rect = self.frame
        rect.origin = origin
        self.frame = rect
    }
}

アニメーションさせる

今回はCADisplayLinkを使って適当にアニメーションさせます。

ViewController.swift
import UIKit

class ViewController: UIViewController {

    //MARK: - Properties
    //MARK: Public

    //MARK: Private
    private var elevateLabel : PMElevateLabel!
    private var animationStartTime : CFTimeInterval?

    //MARK: - View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        elevateLabel = PMElevateLabel(frame: CGRectMake(0, 0, 100, 100))
        elevateLabel.center = CGPointMake(self.view.frame.width / 2, self.view.frame.height / 2)
        elevateLabel.layer.borderColor = UIColor.blueColor().CGColor
        elevateLabel.layer.borderWidth = 1.0
        self.view.addSubview(elevateLabel)

        self.startAnimation()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    //MARK: - Private method
    private func startAnimation() {
        let displayLink = CADisplayLink(target: self, selector: "updateDisplayLink:")
        displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)

        self.animationStartTime = CACurrentMediaTime()
    }

    //MARK: - CADislayLink handler
    @objc private func updateDisplayLink(displayLink : CADisplayLink) {
        guard let animTime = self.animationStartTime else {
            displayLink.invalidate()
            return
        }

        let elapsedTime = displayLink.timestamp - animTime
        if elapsedTime >= 30 {
            displayLink.invalidate()
        }

        elevateLabel.setValue(Int(elapsedTime), animated: true)
    }
}

終わりに

やっつけですが、UILabelを使ったお手軽アニメーションを実装してみました。
現状は数値を渡して、それをもとにアニメーションするだけです。

といってもCADisplayLinkやタイマーなどで定期的に呼ばないとそれっぽくならないので、あらかじめ配列でデータを渡しておいたり、アニメーションの実装を全て内包してしまったほうが使いやすい気はしてます。

アニメーション自体もかなりシンプルなので、Transformとかその他装飾をしてあげればもうちょっとかっこよくなると思います。

ソースコードは下記githubにあります。

PMElevateLabel - github

11
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12