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