线性重复动画
效果
说明
线性重复的动画可以用在以下的一些场景:
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的相关动画会在进入后台的时候自动移除掉了,所以,从后台进入前台的时候需要手动开启动画:
以下是核心所在: