神奇的CAReplicatorLayer
文檔描述:
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