线性重复动画

线性重复动画

效果

说明

线性重复的动画可以用在以下的一些场景:

1)线性加载效果(如上图)

2)下载箭头的循环出现

源码

https://github.com/YouXianMing/Animations

//
//  ReplicatorLineAnimationView.h
//  Animations
//
//  Created by YouXianMing on 16/4/12.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef enum : NSUInteger {
    
    kReplicatorLeft,
    kReplicatorRight,
    kReplicatorUp,
    kReplicatorDown
    
} EReplicatorLineDirection;

@interface ReplicatorLineAnimationView : UIView

/**
 *  Animation's direction.
 */
@property (nonatomic) EReplicatorLineDirection  direction;

/**
 *  Animation's speed.
 */
@property (nonatomic) CGFloat           speed;

/**
 *  Animation's image.
 */
@property (nonatomic, strong) UIImage  *image;

/**
 *  Start animation.
 */
- (void)startAnimation;

@end
//
//  ReplicatorLineAnimationView.m
//  Animations
//
//  Created by YouXianMing on 16/4/12.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "ReplicatorLineAnimationView.h"

@interface ReplicatorLineAnimationView () {
    
    CAReplicatorLayer *_replicatorLayer;
    CALayer           *_animationLayer;
    NSString          *_animationKeyPath;
    CGFloat            _animationToValue;
    CGFloat            _offsetX;
    CGFloat            _offsetY;
    CATransform3D      _instanceTransform;
    BOOL               _startAnimation;
}

@end

@implementation ReplicatorLineAnimationView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        self.speed             = 2.f;
        _replicatorLayer       = [CAReplicatorLayer layer];
        _replicatorLayer.frame = self.bounds;
        [self.layer addSublayer:_replicatorLayer];
        
        _animationLayer       = [CALayer layer];
        _animationLayer.frame = self.bounds;
        [_replicatorLayer addSublayer:_animationLayer];
        
        self.layer.masksToBounds = YES;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidBecomeActive:)
                                                     name:UIApplicationDidBecomeActiveNotification object:nil];
    }
    
    return self;
}

- (void)startAnimation {
    
    _startAnimation = YES;
    
    if (_animationKeyPath.length) {
        
        [_animationLayer removeAnimationForKey:_animationKeyPath];
    }
    
    [self dealWithTheEReplicatorLineDirection];
    
    _replicatorLayer.instanceCount      = 2;
    _replicatorLayer.instanceTransform  = _instanceTransform;
    _animationLayer.contents            = (__bridge id _Nullable)(self.image.CGImage);
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:_animationKeyPath];
    animation.toValue           = @(_animationToValue);
    animation.duration          = 1.f / self.speed;
    animation.timingFunction    = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.repeatCount       = HUGE_VALF;
    [_animationLayer addAnimation:animation forKey:_animationKeyPath];
}

- (void)dealWithTheEReplicatorLineDirection {
    
    if (_direction == kReplicatorLeft || _direction == kReplicatorRight) {
        
        _animationKeyPath  = @"position.x";
        _offsetX           = _direction == kReplicatorLeft ? self.frame.size.width : -self.frame.size.width;
        _offsetY           = 0;
        _animationToValue  = _animationLayer.position.x - _offsetX;
        _instanceTransform = CATransform3DMakeTranslation(_offsetX, 0.0, 0.0);
        
    } else if (_direction == kReplicatorUp || _direction == kReplicatorDown) {
        
        _animationKeyPath  = @"position.y";
        _offsetX           = 0;
        _offsetY           = _direction == kReplicatorUp ? self.frame.size.height : -self.frame.size.height;
        _animationToValue  = _animationLayer.position.y - _offsetY;
        _instanceTransform = CATransform3DMakeTranslation(0.0, _offsetY, 0.0);
    }
}

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}

- (void)eventDidBecomeActive:(id)obj {
    
    NSNotification *fication = obj;
    
    if ([fication.name isEqualToString:UIApplicationDidBecomeActiveNotification]) {
        
        if (_startAnimation == YES) {
            
            [self startAnimation];
        }
    }
}

@end

细节

线性重复动画是有着方向性的,他有4个方向可供你使用:

你需要设置方向值、速度值以及一张可以循环显示的图片,对图片也是有要求的,图片的话需要保证平移的时候可以无缝衔接:

CALayer的相关动画会在进入后台的时候自动移除掉了,所以,从后台进入前台的时候需要手动开启动画:

以下是核心所在:

原文地址:https://www.cnblogs.com/YouXianMing/p/5381717.html