神奇的CAReplicatorLayer

fnln0755 7年前發布 | 7K 次閱讀 iOS開發 移動開發

文檔描述:

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.

簡介

  • 支持系統:>=iOS3.0。
  • 文檔釋義:CAReplicatorLayer類可用來從layer源高效復制多個實體對象,每個實體對象都可以擁有幾何形狀、顏色、時間層次上的不同轉換。
  • 實際應用: 加載動畫、鏡像layer的生成。

使用示例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; }</code></pre>

效果圖如下:

?

鏡像層.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;</code></pre>

    2.并且聲明了一個枚舉類型:該枚舉類型代表著加載動畫類型。

    typedef  NS_ENUM(NSInteger,JHHJViewType){
    /**
    • 線性動畫 */ JHHJViewTypeSingleLine = 0,

/**

  • 方形點動畫 */ JHHJViewTypeSquare = 1,

/**

  • 三角形運動動畫 */ JHHJViewTypeTriangleTranslate = 2,

/**

  • 原型視圖裁剪動畫 / JHHJViewTypeClip };</code></pre>

    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</code></pre> 
    

    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; }</code></pre>

      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]; }</code></pre>

    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.0M_PI/180.0, 0.0, 0.0, 1.0); replicatorLayer.instanceTransform = trans3D; [replicatorLayer addSublayer:shape]; return replicatorLayer; }</code></pre>

流程如上,效果圖如下:

loading......

來自:https://github.com/China131/JHLoadingForHJ
 

https://github.com/China131/JHLoadingForHJ

 

 本文由用戶 fnln0755 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!