记录一下最近的动画实现,通过文档以及调试的知识tip积累。
1. 组合动画对象尽量不要保存为全局属性或者变量。
2.CAKeyframeAnimation .values 以及.keyTimes是一一对应, keyTimes 的取值是【0~1】,这里是按照时间取值的。
3.CAAnimationGroup 这个动画组的时间是所有动画的总时间, 多余的时间会被CAAnimationGroup 的duration裁剪。
NSString * const AnimationKey = @"AnimationKey";
NSString * const TwelveFrameAnimation = @"TwelveFrameAnimation";
NSString * const FourteenFrameAnimation = @"FourteenFrameAnimation";
NSString * const EightteenFrameAnimation = @"EightteenFrameAnimation";
NSString * const ThirtyFrameAnimation = @"ThirtyFrameAnimation";
NSString * const SixteenFrameAnimation = @"SixteenFrameAnimation";
NSString * const CircleImageViewValue = @"CircleImageViewValue";
NSString * const FAGuideAnimationXPath = @"transform.translation.x";
NSString * const FAGuideAnimationYPath = @"transform.translation.y";
NSString * const FAGuideAnimationZPath = @"transform.rotation.z";
NSString * const FAGuideAnimationOpacity = @"opacity";
NSString * const FAGuideAnimationPath = @"path";
NSInteger const frame = 24.000;
@interface GestureGuideView ()<CAAnimationDelegate>
/// 手势图片
@property (nonatomic, strong) UIImageView *handImageView;
@property (nonatomic, strong) CAShapeLayer *radarLayer;
/// 描述
@property (nonatomic, strong) UILabel *desLabel;
@property (nonatomic, copy) void(^complete)(void);
@end
@implementation GestureGuideView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self addSubview:self.handImageView];
[self addSubview:self.desLabel];
self.backgroundColor = [UIColor redColor];
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickGesGudieView)]];
}
return self;
}
- (UILabel *)desLabel
{
if (!_desLabel)
{
_desLabel = [[UILabel alloc] init];
_desLabel.textColor = HexColor(0xFFFFFF);
_desLabel.top = self.handImageView.bottom+10.0f;
_desLabel.width = self.width;
_desLabel.height = 14.0f;
_desLabel.textAlignment = NSTextAlignmentCenter;
}
return _desLabel;
}
- (CGFloat)handViewX
{
return self.centerX + 12.0f - self.handImageView.width/2.0f;
}
- (CGFloat)handViewY
{
return self.height/3.0 - self.handImageView.height;
}
- (UIImageView *)handImageView
{
if (!_handImageView)
{
_handImageView = [[UIImageView alloc] init];
UIImage *image = FAIMAGE(@"fx_hander_click");
_handImageView.image = image;
_handImageView.width = image.size.width;
_handImageView.height = image.size.height;
_handImageView.x = [self handViewX];
_handImageView.y = [self handViewY];
_handImageView.alpha = 0;
[self addSubview:_handImageView];
}
return _handImageView;
}
- (CAShapeLayer *)radarLayer
{
if (!_radarLayer)
{
_radarLayer = [CAShapeLayer layer];
CGPoint centerPoint = CGPointMake([self handViewX] - 12, [self handViewY] - 18);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:centerPoint
radius:10
startAngle:0
endAngle:2 * M_PI
clockwise:YES];
_radarLayer.frame = CGRectMake(centerPoint.x, centerPoint.y, 10, 10);
_radarLayer.fillColor = [UIColor whiteColor].CGColor;
_radarLayer.opacity = 0;
_radarLayer.path = path.CGPath;
[self.layer insertSublayer:_radarLayer above:0];
}
return _radarLayer;
}
- (void)clickGesGudieView
{
if (self.superview)
{
[self removeFromSuperview];
if (self.complete)
{
self.complete();
}
[self.handImageView.layer removeAllAnimations];
[self.radarLayer removeAllAnimations];
}
}
- (void)startAnimation:(void(^)(void))complete
{
self.complete = complete;
[self startAnima];
}
- (void)startAnima
{
self.handImageView.layer.anchorPoint = CGPointMake(0.5, 1);
self.handImageView.layer.position = CGPointMake(self.handImageView.centerX, [self handViewY]+self.handImageView.height);
[self handImageViewAnimation];
}
- (void)shapeLayerAnimation
{
[self.radarLayer addAnimation:[self cicleAnimationGroup:0] forKey:CircleImageViewValue];
[self.radarLayer addAnimation:[self cicleAnimationGroup:4/frame] forKey:CircleImageViewValue];
}
- (void)handImageViewAnimation
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self.handImageView.layer addAnimation:[self twelveFrameAnimation] forKey:TwelveFrameAnimation];
}
- (CAAnimationGroup *)thirtyFrameAnimation
{
CGFloat duration = 12.000/frame;
CAKeyframeAnimation *animationY = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationYPath];
animationY.duration = duration;
animationY.values = @[@(-18.0f),@(0)];
animationY.keyTimes = @[@(0), @(1)];
CAKeyframeAnimation *animationX = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationXPath];
animationX.duration = duration;
animationX.values = @[@(-12.0f), @(0)];
animationX.keyTimes = @[@(0), @(1)];
CAKeyframeAnimation *animationOpacity = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationOpacity];
animationOpacity.duration = duration;
animationOpacity.values = @[@(1), @(0)];
animationOpacity.keyTimes = @[@(0), @(1)];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[animationY,animationX, animationOpacity];
group.duration = duration;
group.repeatCount = 1;
group.beginTime = CACurrentMediaTime();
group.delegate = self;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
[group setValue:ThirtyFrameAnimation forKey:AnimationKey];
return group;
}
- (CAKeyframeAnimation *)eightteenFrameAnimation
{
CGFloat duration = 2.000/frame;
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationZPath];
animation.duration = duration;
animation.beginTime = CACurrentMediaTime();
animation.values = @[@(M_PI/9),@(0)];
animation.keyTimes = @[@(0),@(1)];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.delegate = self;
[animation setValue:EightteenFrameAnimation forKey:AnimationKey];
return animation;
}
- (CAKeyframeAnimation *)sixteenFrameAnimation
{
CGFloat duration = 2.000/frame;
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationZPath];
animation.duration = duration;
animation.beginTime = CACurrentMediaTime();
animation.values = @[@(0),@(M_PI/9)];
animation.keyTimes = @[@(0),@(1)];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[animation setValue:SixteenFrameAnimation forKey:AnimationKey];
animation.delegate = self;
return animation;
}
- (CAKeyframeAnimation *)fourteenFrameAnimation
{
CGFloat duration = 2.000/frame;
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationZPath];
animation.duration = duration;
animation.beginTime = CACurrentMediaTime();
animation.values = @[@(M_PI/9),@(0)];
animation.keyTimes = @[@(0),@(1)];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.delegate = self;
[animation setValue:FourteenFrameAnimation forKey:AnimationKey];
return animation;
}
- (CAAnimationGroup *)twelveFrameAnimation
{
CGFloat duration = 12.000/frame;
CAKeyframeAnimation *rotation = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationZPath];
rotation.duration = duration;
rotation.values = @[@(0),@(M_PI/9)];
rotation.keyTimes = @[@(0),@(1)];
CAKeyframeAnimation *animationY = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationYPath];
animationY.duration = duration;
animationY.values = @[@(0),@(-18.0f)];
animationY.keyTimes = @[@(0), @(1)];
CAKeyframeAnimation *animationX = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationXPath];
animationX.duration = duration;
animationX.values = @[@(0), @(-12.0f)];
animationX.keyTimes = @[@(0), @(1)];
// 透明值
CAKeyframeAnimation *animationOpacity = [CAKeyframeAnimation animationWithKeyPath:FAGuideAnimationOpacity];
animationOpacity.duration = duration;
animationOpacity.values = @[@(0), @(1)];
animationOpacity.keyTimes = @[@(0), @(1)];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[rotation,animationY,animationX, animationOpacity];
group.duration = duration;
group.repeatCount = 1;
group.delegate = self;
group.beginTime = CACurrentMediaTime();
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[group setValue:TwelveFrameAnimation forKey:AnimationKey];
return group;
}
- (CAAnimationGroup *)cicleAnimationGroup:(CGFloat)delay
{
CABasicAnimation *basicAnimation = [CABasicAnimation animation];
basicAnimation.keyPath = FAGuideAnimationPath;
CGPoint center = CGPointMake(self.radarLayer.bounds.size.width/2, self.radarLayer.bounds.size.height/2);
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:10 startAngle:0 endAngle:2 * M_PI clockwise:YES];
UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:18 startAngle:0 endAngle:2 * M_PI clockwise:YES];
UIBezierPath *path3 = [UIBezierPath bezierPathWithArcCenter:center radius:25 startAngle:0 endAngle:2 * M_PI clockwise:YES];
basicAnimation.fromValue = (__bridge id _Nullable)(path1.CGPath);
basicAnimation.byValue = (__bridge id _Nullable)(path2.CGPath);
basicAnimation.toValue = (__bridge id _Nullable)(path3.CGPath);
basicAnimation.fillMode = kCAFillModeForwards;
CABasicAnimation *opacityAnimation = [CABasicAnimation animation];
opacityAnimation.keyPath = FAGuideAnimationOpacity;
opacityAnimation.fromValue = @(0.3);
opacityAnimation.toValue = @(0);
opacityAnimation.fillMode = kCAFillModeForwards;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[basicAnimation,opacityAnimation];
group.duration = 6.000/frame;
group.beginTime = CACurrentMediaTime() + delay;
group.repeatCount = 1;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
group.removedOnCompletion = YES;
return group;
}
#pragma - delegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
if (flag)
{
NSString *animationName = [NSString stringWithFormat:@"%@",[anim valueForKey:AnimationKey]];
if ([animationName isEqualToString:ThirtyFrameAnimation])
{
[self performSelector:@selector(handImageViewAnimation) withObject:nil afterDelay:.2];
}
else if ([animationName isEqualToString:TwelveFrameAnimation])
{
[self.handImageView.layer addAnimation:[self fourteenFrameAnimation] forKey:FourteenFrameAnimation];
}
else if ([animationName isEqualToString:FourteenFrameAnimation])
{
[self.handImageView.layer addAnimation:[self sixteenFrameAnimation] forKey:SixteenFrameAnimation];
[self shapeLayerAnimation];
}
else if ([animationName isEqualToString:SixteenFrameAnimation])
{
[self.handImageView.layer addAnimation:[self eightteenFrameAnimation] forKey:EightteenFrameAnimation];
}
else if ([animationName isEqualToString:EightteenFrameAnimation])
{
[self.handImageView.layer addAnimation:[self thirtyFrameAnimation] forKey:TwelveFrameAnimation];
[self shapeLayerAnimation];
}
}
}
网友评论