33
30

More than 5 years have passed since last update.

CADisplayLinkを使ったUILabelのアニメーション

Posted at

はじめに

UILabelで数値をアニメーションしてカウントしたい場合の処理を
CADisplayLinkを使用して実装してみます。

UILabelサブクラスの作成

UILabelのサブクラスを作成します。例ではPMAnimationLabelという名前にしました。
そしてアニメーションを実行するメソッド(animationFrom:flag_to:withDuration:)を追加します。

PMAnimationLabel.h
@interface PMAnimationLabel : UILabel

-(void)animationFrom:(float)fromValue to:(float)toValue withDuration:(NSTimeInterval)duration;

@end

アニメーション処理の実装

PMAnimationLabel.mファイルにアニメーション処理を実装していきます。

PMAnimationLabel.m

//プロパティ
@interface PMAnimationLabel()
@property (nonatomic, assign) float startValue,endValue,rate,totaltime;
@property (nonatomic, assign) CFTimeInterval startTime;
@end

@implementation PMAnimationLabel

#pragma mark -- Class Method --

-(void)animationFrom:(float)fromValue to:(float)toValue withDuration:(NSTimeInterval)duration{
    self.startValue = fromValue; //アニメーション開始時の値
    self.endValue = toValue; //アニメーション終了時の値
    self.totaltime = duration; //アニメーションの時間

    self.text = [self getTextFromProgress:self.startValue];

    //CADisplayLinkの生成とコールバックの登録
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateValue:)];
    self.startTime = CACurrentMediaTime();
    [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}

#pragma mark -- Private Method --

-(void)updateValue:(CADisplayLink *)link{
    float dt = ([link timestamp] - self.startTime) / self.totaltime;
    if (dt >= 1.0) {
        self.text = [self getTextFromProgress:self.endValue];
        [link removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
        return;
    }

    float current = (self.endValue - self.startValue) * dt + self.startValue;
    self.text = [self getTextFromProgress:current];
}

-(NSString *)getTextFromProgress:(CGFloat)progress{
    return [NSString stringWithFormat:@"%i",percentage];
}

@end

アニメーションの実行

PMAnimationLabelを使用したいViewなどに追加してアニメーション用のメソッドを呼び出します。
(frameの設定、addSubView:などの処理は割愛します。)

PMAnimationLabel *animationLabel = [PMAnimationLabel new];
[animationLabel animationFrom:0 to:100 withDuration:3.0];

終わりに

CADisplayLinkはディスプレイのリフレッシュに同期してRunLoopを発生させるもののようで、
NSTimerと似たような実装が可能ですが、定期的な処理を実行する場合はCADisplayLinkの方が適切なようです。
(ここは自分もよく調べられてないので自信があまりないですが。。。)

参考資料

33
30
1

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
33
30