基于CAReplicatorLayer的炫酷动画
为了方便调用,我把相关方法写成了类方法。调用每个方法会返回一个CAReplicatorLayer的实例,然后把该实例添加到目标试图的layer上即可。
首先是公开的外部接口,具体如下:
#import <Foundation/Foundation.h>
@interface WHAnimation : NSObject
+ (CALayer *)replicatorLayer_Circle;
+ (CALayer *)replicatorLayer_Wave;
+ (CALayer *)replicatorLayer_Triangle;
+ (CALayer *)replicatorLayer_Grid;
@end
接下来是内部实现,因为会用到一些CAAnimationGroup,子动画我都分开写了,所以篇幅不少,具体如下:
#import "WHAnimation.h"
@implementation WHAnimation
+ (CALayer *)replicatorLayer_Circle{
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, 0, 80, 80);
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 80, 80)].CGPath;
shape.fillColor = [UIColor redColor].CGColor;
shape.opacity = 0.0;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = @[[WHAnimation alphaAnimation],[WHAnimation scaleAnimation]];
animationGroup.duration = 4.0;
animationGroup.autoreverses = NO;
animationGroup.repeatCount = HUGE;
[shape addAnimation:animationGroup forKey:@"animationGroup"];
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = CGRectMake(0, 0, 80, 80);
replicatorLayer.instanceDelay = 0.5;
replicatorLayer.instanceCount = 8;
[replicatorLayer addSublayer:shape];
return replicatorLayer;
}
+ (CALayer *)replicatorLayer_Wave{
CGFloat between = 5.0;
CGFloat radius = (100-2*between)/3;
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, (100-radius)/2, radius, radius);
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath;
shape.fillColor = [UIColor redColor].CGColor;
[shape addAnimation:[WHAnimation scaleAnimation1] forKey:@"scaleAnimation"];
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = CGRectMake(0, 0, 100, 100);
replicatorLayer.instanceDelay = 0.2;
replicatorLayer.instanceCount = 3;
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(between*2+radius,0,0);
[replicatorLayer addSublayer:shape];
return replicatorLayer;
}
+ (CALayer *)replicatorLayer_Triangle{
CGFloat radius = 100/4;
CGFloat transX = 100 - radius;
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, 0, radius, radius);
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath;
shape.strokeColor = [UIColor redColor].CGColor;
shape.fillColor = [UIColor redColor].CGColor;
shape.lineWidth = 1;
[shape addAnimation:[WHAnimation rotationAnimation:transX] forKey:@"rotateAnimation"];
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = CGRectMake(0, 0, radius, radius);
replicatorLayer.instanceDelay = 0.0;
replicatorLayer.instanceCount = 3;
CATransform3D trans3D = CATransform3DIdentity;
trans3D = CATransform3DTranslate(trans3D, transX, 0, 0);
trans3D = CATransform3DRotate(trans3D, 120.0*M_PI/180.0, 0.0, 0.0, 1.0);
replicatorLayer.instanceTransform = trans3D;
[replicatorLayer addSublayer:shape];
return replicatorLayer;
}
+ (CALayer *)replicatorLayer_Grid{
NSInteger column = 3;
CGFloat between = 5.0;
CGFloat radius = (100 - between * (column - 1))/column;
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, 0, radius, radius);
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath;
shape.fillColor = [UIColor redColor].CGColor;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = @[[WHAnimation scaleAnimation1], [WHAnimation alphaAnimation]];
animationGroup.duration = 1.0;
animationGroup.autoreverses = YES;
animationGroup.repeatCount = HUGE;
[shape addAnimation:animationGroup forKey:@"groupAnimation"];
CAReplicatorLayer *replicatorLayerX = [CAReplicatorLayer layer];
replicatorLayerX.frame = CGRectMake(0, 0, 100, 100);
replicatorLayerX.instanceDelay = 0.3;
replicatorLayerX.instanceCount = column;
replicatorLayerX.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, radius+between, 0, 0);
[replicatorLayerX addSublayer:shape];
CAReplicatorLayer *replicatorLayerY = [CAReplicatorLayer layer];
replicatorLayerY.frame = CGRectMake(0, 0, 100, 100);
replicatorLayerY.instanceDelay = 0.3;
replicatorLayerY.instanceCount = column;
replicatorLayerY.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, 0, radius+between, 0);
[replicatorLayerY addSublayer:replicatorLayerX];
return replicatorLayerY;
}
+ (CABasicAnimation *)alphaAnimation{
CABasicAnimation *alpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
alpha.fromValue = @(1.0);
alpha.toValue = @(0.0);
return alpha;
}
+ (CABasicAnimation *)scaleAnimation{
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"];
scale.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 0.0)];
scale.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)];
return scale;
}
+ (CABasicAnimation *)scaleAnimation1{
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"];
scale.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)];
scale.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.2, 0.2, 0.0)];
scale.autoreverses = YES;
scale.repeatCount = HUGE;
scale.duration = 0.6;
return scale;
}
+ (CABasicAnimation *)rotationAnimation:(CGFloat)transX{
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D fromValue = CATransform3DRotate(CATransform3DIdentity, 0.0, 0.0, 0.0, 0.0);
scale.fromValue = [NSValue valueWithCATransform3D:fromValue];
CATransform3D toValue = CATransform3DTranslate(CATransform3DIdentity, transX, 0.0, 0.0);
toValue = CATransform3DRotate(toValue,120.0*M_PI/180.0, 0.0, 0.0, 1.0);
scale.toValue = [NSValue valueWithCATransform3D:toValue];
scale.autoreverses = NO;
scale.repeatCount = HUGE;
scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
scale.duration = 0.8;
return scale;
}
@end