神奇的CAReplicatorLayer

fnln0755 5年前
   <h2>文档描述:</h2>    <p>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.</p>    <h2>简介</h2>    <ul>     <li>支持系统:>=iOS3.0。</li>     <li>文档释义:CAReplicatorLayer类可用来从layer源高效复制多个实体对象,每个实体对象都可以拥有几何形状、颜色、时间层次上的不同转换。</li>     <li>实际应用: 加载动画、镜像layer的生成。</li>    </ul>    <h2>使用示例1:实现一个镜像反射效果</h2>    <h3>1.创建一个模板层</h3>    <pre>  <code class="language-objectivec">/*        创建一个模板层 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];</code></pre>    <p>Note:在这里,大家可以根据需要添加不同的动画元素或者不添加任何动画,该用法多用于实现加载提示视图的动画制作。</p>    <h3>2.实现某个视图的反射效果</h3>    <p>我们首先继承UIView创建一个子类,在子类的+(Class)layerClass方法中设置当前视图对象的layer为CAReplicatorLayer对象:</p>    <pre>  <code class="language-objectivec">+ (Class)layerClass{     return [CAReplicatorLayer class];    }</code></pre>    <p>然后在创建该子类的对象时对self.layer进行设置相关参数:</p>    <pre>  <code class="language-objectivec">- (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;  }</code></pre>    <p>效果图如下:</p>    <p></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/9f921b3ada0f51e9bdde319bf3f8e577.png"></p>    <p style="text-align:center">镜像层.png</p>    <h2>示例2:CAReplicatorLayer作为核心技术实现加载动画。</h2>    <h3>1.首先,创建一个UIView的子类,并暴露相关方法:</h3>    <pre>  <code class="language-objectivec">@interface JHHJView : UIView  /*        显示加载动画 并添加到父视图上         */  + (void)showLoadingOnView:(UIView *)superView Type:(JHHJViewType)type;  /*        显示动画 并添加在主窗口上         */  + (void)showLoadingOnTheKeyWindowWithType:(JHHJViewType)type;  /*        停止动画         */  + (void)hideLoading;  /*        设置动画背景色(全屏背景色)         */  + (void)backgroudColor:(UIColor *)color;  /*        设置中心视图的动画背景颜色 默认透明色         */  + (void)centerBGViewBackgroudColor:(UIColor *)color;</code></pre>    <h3>2.并且声明了一个枚举类型:该枚举类型代表着加载动画类型。</h3>    <pre>  <code class="language-objectivec">typedef  NS_ENUM(NSInteger,JHHJViewType){  /**   *  线性动画   */  JHHJViewTypeSingleLine = 0,    /**   *  方形点动画   */  JHHJViewTypeSquare = 1,    /**   *  三角形运动动画   */  JHHJViewTypeTriangleTranslate = 2,    /**   *  原型视图裁剪动画   */  JHHJViewTypeClip  };</code></pre>    <h3>3.在.m文件中,该类拥有的成员变量如下:</h3>    <pre>  <code class="language-objectivec">@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</code></pre>    <h3>4.然后,设置以单例的方式创建该类的对象:</h3>    <pre>  <code class="language-objectivec">/**   *  对象单例化  *   *  @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;  }</code></pre>    <h3>5.动画的实现如下:</h3>    <pre>  <code class="language-objectivec">/**   *  展示动画视图 并添加到依赖视图上   *  *  @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];  }</code></pre>    <h3>6.下面来具体实现其中一个动画,以三角形旋转动画为例:</h3>    <pre>  <code class="language-objectivec">/**  *  三角形运动动画   *  *  @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;  }</code></pre>    <p>流程如上,效果图如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7768d3e8df0c3a22e3210c1e177872d5.gif"></p>    <p style="text-align:center">loading......</p>    <p>来自:https://github.com/China131/JHLoadingForHJ<br>  </p>    <p>https://github.com/China131/JHLoadingForHJ</p>    <p> </p>