iOS 画图iOS技术交流iOS 动画家族

神奇的CAReplicatorLayer

2016-12-27  本文已影响497人  不睡觉的鸟

文档描述:

The CAReplicatorLayer class creates a specified number of copies of its sublayers (the source layer), each copy potentially having geometric, temporal and color transformations applied to it.

简介

使用示例1:实现一个镜像反射效果

1.创建一个模板层

  /*        创建一个模板层 CAReplicatorLayer会按照一定的规则“克隆”这个模板         */
  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 = @[[self alphaAnimation],[self scaleAnimation]];
  /*        动画执行时间         */
  animationGroup.duration = 4.0;
  animationGroup.autoreverses = NO;
  animationGroup.repeatCount = HUGE;
  /*        给模板层添加动画 实质上也是给每个CAReplicatorLayer子层添加动画         */
  [shape addAnimation:animationGroup forKey:@"animationGroup"];
  /*        创建CAReplicatorLayer对象         */
  CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
  replicatorLayer.frame = self.containerView.bounds;
  /*        设置每个元素的添加间隔时间         */
  replicatorLayer.instanceDelay = 0.5;
  /*        设置每元素个数         */
  replicatorLayer.instanceCount = 8;
  /*        给CAReplicatorLayer对象的子层添加转换规则 这里决定了子层的布局         */
  replicatorLayerY.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, 0, radius+between, 0);
  /*        添加子层         */
  [replicatorLayer addSublayer:shape];

Note:在这里,大家可以根据需要添加不同的动画元素或者不添加任何动画,该用法多用于实现加载提示视图的动画制作。

2.实现某个视图的反射效果

我们首先继承UIView创建一个子类,在子类的+(Class)layerClass方法中设置当前视图对象的layer为CAReplicatorLayer对象:

  + (Class)layerClass{
   return [CAReplicatorLayer class];
  }

然后在创建该子类的对象时对self.layer进行设置相关参数:

- (void)setup{
/*        获取当前的layer 实际上为CAReplicatorLayer对象         */
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.instanceCount = 2;
layer.anchorPoint = CGPointMake(0.5, 0.5);

/*        创建3D转换效果         */
CATransform3D transform = CATransform3DIdentity;
CGFloat verticaloffset = self.bounds.size.height  ;
transform = CATransform3DTranslate(transform, 0, verticaloffset, 0);

/*        设置Y轴镜面反射         */
transform = CATransform3DScale(transform, 1, -1, 0);
transform = CATransform3DRotate(transform, -M_PI / 4, 1, 0, 0);
layer.instanceTransform  = transform;
/*        镜面的透明度 越低显示越清晰 因为是镜面效果         */
layer.instanceAlphaOffset = -0.1;
}

效果图如下:


镜像层.png

示例2:CAReplicatorLayer作为核心技术实现加载动画。

1.首先,创建一个UIView的子类,并暴露相关方法:

@interface JHHJView : UIView
/*        显示加载动画 并添加到父视图上         */
+ (void)showLoadingOnView:(UIView *)superView Type:(JHHJViewType)type;
/*        显示动画 并添加在主窗口上         */
+ (void)showLoadingOnTheKeyWindowWithType:(JHHJViewType)type;
/*        停止动画         */
+ (void)hideLoading;
/*        设置动画背景色(全屏背景色)         */
+ (void)backgroudColor:(UIColor *)color;
/*        设置中心视图的动画背景颜色 默认透明色         */
+ (void)centerBGViewBackgroudColor:(UIColor *)color;

2.并且声明了一个枚举类型:该枚举类型代表着加载动画类型。

typedef  NS_ENUM(NSInteger,JHHJViewType){
/**
 *  线性动画
 */
JHHJViewTypeSingleLine = 0,

/**
 *  方形点动画
 */
JHHJViewTypeSquare = 1,

/**
 *  三角形运动动画
 */
JHHJViewTypeTriangleTranslate = 2,

/**
 *  原型视图裁剪动画
 */
JHHJViewTypeClip
};

3.在.m文件中,该类拥有的成员变量如下:

@interface JHHJView ()
//中心背景视图
@property (nonatomic,strong)JHHJCenterBGView *centerBGView;
//计时器
@property (nonatomic,strong)NSTimer * clipTimer;
//层数组
@property (nonatomic,strong)NSMutableArray * clipLayerArr;
//计时器计量数
@property (nonatomic,assign) long long currentTimerIndex;
//背景层
@property (nonatomic,strong) CAShapeLayer *bgLayer;
@end

4.然后,设置以单例的方式创建该类的对象:

/**
 *  对象单例化
*
 *  @return 单例对象
*/
+ (JHHJView *)shareInstanceJHHJView{
static JHHJView * instance = nil;
if (!instance) {
    instance                     = [[JHHJView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    instance.centerBGView        = [[JHHJCenterBGView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    instance.centerBGView.center = CGPointMake(K_IOS_WIDTH / 2, K_IOS_HEIGHT/2);
    [instance addSubview:instance.centerBGView];
}
return instance;
}

5.动画的实现如下:

/**
 *  展示动画视图 并添加到依赖视图上
 *
*  @param superView 依赖的父视图
*  @param type      动画样式
*/
+ (void)showLoadingOnView:(UIView *)superView Type:(JHHJViewType)type{
/*        在显示前  先从父视图移除当前动画视图         */
JHHJView *instance = [[self class] shareInstanceJHHJView];
[[self class] hideLoading];
/*        显示前 先将动画图层从中心视图上移除         */
for (CALayer *layer in instance.centerBGView.layer.sublayers) {
    [layer removeFromSuperlayer];
}
/*        按照type初始化动画         */
switch (type) {
    case JHHJViewTypeSingleLine:
    {
        CALayer *layer = [instance lineAnimation];
        layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 - 25, CGRectGetHeight(instance.centerBGView.frame)/2);
        [instance.centerBGView.layer addSublayer:layer];
    }break;
        
    case JHHJViewTypeSquare:
    {
        CALayer *layer = [[self class] qurareAnimation];
        layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2, CGRectGetHeight(instance.centerBGView.frame)/2);
        [instance.centerBGView.layer addSublayer:layer];
    }break;
    case JHHJViewTypeTriangleTranslate:
    {
        CALayer *layer = [[self class] triangleAnimation];
        layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 - 18, CGRectGetHeight(instance.centerBGView.frame)/2 - 15);
        [instance.centerBGView.layer addSublayer:layer];
    }break;
    case JHHJViewTypeClip:
    {
        
        CALayer *layer = [[self class] clipAnimation];
        layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 , CGRectGetHeight(instance.centerBGView.frame)/2 - 15);
        [instance.centerBGView.layer addSublayer:layer];
        
    }break;
    default:
        break;
}
[superView addSubview:instance];
}

6.下面来具体实现其中一个动画,以三角形旋转动画为例:

/**
*  三角形运动动画
 *
*  @return 动画实例对象
 */
+ (CALayer *)triangleAnimation{
/*        基本间距确定及模板层的创建         */
CGFloat radius                     = 50/4.0;
CGFloat transX                     = 50 - 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:[JHHJAnimation rotateAnimation] 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;
}

流程如上,效果图如下:

loading......
想要了解更多,源码在这里哦......
上一篇下一篇

猜你喜欢

热点阅读