基于CoreAnimation的数字动画Label

基于CoreAnimation的数字动画Label_第1张图片
WYCountingLabel.gif

心路简介

CoreAnimation中有fromValuetoValue我就在想,如果把这个东西放到Label上,让label的文字跟随数字的变化而变化,这样变化的Label不就出来了吗。

一、动画设计

CoreAnimation是添加到layer上的,所以需要先创建一个自定义的WYCountingLayer,要跟随数字而变化,所以我增加了一个 wy_number属性,并且使用@dynamic修饰该属性。

1.想要在属性改变的时候重绘,需要重写needsDisplayForKey:当layer的属性发生改变的时候就会通过这个方法询问是否需要对当前layer进行重绘。

NSString *const WYAnimationKey = @"wy_number";
+ (BOOL)needsDisplayForKey:(NSString *)key {
    if ([key isEqualToString:WYAnimationKey]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

2.为wy_number增加CABasicAnimation,这样当wy_number发生改变的时候就会有动画效果了,layer的隐式动画的实现原理就是这样的

- (id)actionForKey:(NSString *)event {
    if (self.presentationLayer) {
        if ([event isEqualToString:WYAnimationKey]) {
            CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:WYAnimationKey];
            animation.fromValue = [self.presentationLayer valueForKey:WYAnimationKey];
            return animation;
        }
    }
    return [super actionForKey:event];
}

3.创建一个WYCountingLabel的类并且有一个wy_number的属性

@interface WYCountingLabel()

@property (nonatomic, strong) WYCountingLayer *countingLayer;

@end

@implementation WYCountingLabel

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setupLayer];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    
    [self setupLayer];
}

- (void)setupLayer {
    // 一定要给countingLayer设置frame并且添加到label的layer上
    // 否则countingLayer的drawInContex:方法是不会走的
    self.countingLayer = [WYCountingLayer layer];
    self.countingLayer.ownerLabel = self;
    self.countingLayer.frame = self.bounds;
    
    [self.layer addSublayer:_countingLayer];
}

- (void)setWy_number:(double)wy_number {
    _wy_number = wy_number;
    
    self.countingLayer.wy_number = wy_number;
}

4.重写WYCountingLayerdrawInContex:方法,在这个方法中更新label

- (void)drawInContext:(CGContextRef)ctx {
    [self.ownerLabel wy_updateLabelText:self.wy_number];
}

二、项目中使用

只需要把WYCountingLabel这个类拖到项目中即可,我给WYCountingLabel扩展了一个formatBlock可以让label根据数字做一些个性化展示,例如加逗号等。和一个wy_countFrom:to:duration:可以快速给label添加数字动画的方法
github:https://github.com/wangyansnow/WYCountingLabel
例:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.countingLabel = [[WYCountingLabel alloc] initWithFrame:CGRectMake(20, 80, 100, 24)];
    [self.view addSubview:self.countingLabel];

    __weak typeof(self) weakSelf = self;
    [self.countingLabel setWy_FormatBlock:^NSString *(double wy_number){
        return [NSString stringWithFormat:@"%.2f", wy_number];
    }];
    
}

- (IBAction)startCountingBtnClick:(UIButton *)sender {
    static double number = 1340;
    number += 1457;
    
    self.countingLabel.wy_number = number;
}

- (IBAction)fromBtnClick:(UIButton *)sender {
    [self.countingLabel wy_countFrom:0 to:1576 duration:2.0];
}

你可能感兴趣的:(基于CoreAnimation的数字动画Label)