CALayer 实现的动画效果(一)

先看下效果图:

(备注: 上面GIF 是Mac 下录制视频的并转化成gif 的而成,工具为GIF Brewery 3 【这款软件挺不错的】)

那么主题来了如何实现上面效果呢?

1、创建自定义CALayer子类

KBSpinnyMcSpinface

构造函数如下:

-(instancetype)initWithNumberOfItems:(NSUInteger)number {
    if (self = [self init]) {
        self.masksToBounds = NO;
        self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.height);
        for (NSUInteger index = 0; index < number; index++) {
           //创建子layer
           CALayer *layer = [self generLayerWithSize:CGSizeMake(100, 100) index:index];
            [self insertSublayer:layer atIndex:0];
       //每个子类设置不同的层级(z坐标) [self setZPosition:(CGFloat)index forLayer:layer]; } }
return self; }
创建子类cugangenerLayerWithSize方法如下:
-(CAShapeLayer*)generLayerWithSize:(CGSize)size index:(NSInteger)index {
    CAShapeLayer *square = [CAShapeLayer layer];
    square.path = [UIBezierPath   bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:size.width/4 ].CGPath;
    square.bounds = CGPathGetBoundingBox(square.path);
    square.fillColor = [self randColor].CGColor;//我这里设置了随时颜色
    square.position = CGPointMake(150,200);
    [self setAnchorPoint:CGPointMake(0.5, 0.5) forLayer:square];//设置锚点坐标
    return square;
}
指定的CALayer设置锚点坐标方法如下
// Because adjusting the anchorPoint itself adjusts the frame, this is needed to avoid it, and keep the layer stationary.
-(void)setAnchorPoint:(CGPoint)anchorPoint forLayer:(CALayer*)layer {
    CGPoint newPoint = CGPointMake(layer.bounds.size.width * anchorPoint.x, layer.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(layer.bounds.size.width * layer.anchorPoint.x, layer.bounds.size.height * layer.anchorPoint.y);
    CGPoint position = layer.position;
    position.x -= oldPoint.x;
    position.x += newPoint.x;
    position.y -= oldPoint.y;
    position.y += newPoint.y;
    layer.position = position;
    layer.anchorPoint = anchorPoint;
}

获取随机颜色方法如下:

-(UIColor*)randColor {
    CGFloat red =0.0 ,green = 0.0,blue = 0.0 ;
    red  = (CGFloat)(1+arc4random()%99)/100;
    green  = (CGFloat)(1+arc4random()%99)/100;
    blue  = (CGFloat)(1+arc4random()%99)/100;
    UIColor *randColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
    return randColor;
}

子类CALayer   zPosition 设置方法

-(void)setZPosition:(CGFloat)zPosition forLayer:(CALayer*)layer {
    layer.zPosition = zPosition * (-20);
}

2、创建动画

-(void)startAnimation{
    CGFloat offsetTime = 0.0;
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0 / -500.0;
    transform = CATransform3DRotate(transform,M_PI, 0, 0, 1);
    [CATransaction begin];
    for (CALayer *layer in self.sublayers) {
        CABasicAnimation *animation = [self getPinForTranform:transform];
        animation.beginTime = [layer  convertTime:CACurrentMediaTime() toLayer:nil] + offsetTime;
        [layer addAnimation:animation forKey:nil];
        offsetTime += 0.1;
    }
    [CATransaction commit];

}

-(void)stopAnimation {
    for (CALayer *layer in self.sublayers) {
        [layer removeAllAnimations];
    }
}

-(CABasicAnimation*)getPinForTranform:(CATransform3D )transform {
    CABasicAnimation *basic =[CABasicAnimation animationWithKeyPath:@"transform"];
    basic.toValue = [NSValue valueWithCATransform3D:transform];
    basic.duration = 1.0;
    basic.fillMode = kCAFillModeForwards;
    basic.repeatCount = HUGE;
    basic.autoreverses = YES;
    basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    basic.removedOnCompletion = NO;
    return basic;

}

开始运行 ,结果如下:

不是我们的结果啊。。。。。其实这里是因为我们自定义Layer还是2D情况

3、为自定义类添加 3D属性

设置旋转角度方法

//设置本layer 在父layer 中展示3D效果
-(void)rotateParentLayer:(CGFloat)toDegree {
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0 / -500.0;
    transform = CATransform3DRotate(transform, [self degreesToRadians:toDegree], 1, 0, 0);//以x 坐标旋转制定的角度
    self.transform = transform;
}

//角度转弧度
-(CGFloat)degreesToRadians:(CGFloat)degrees {
    return ((M_PI * (degrees)) / 180.0);
}

然后构造函数中调用:

-(instancetype)initWithNumberOfItems:(NSUInteger)number {
    if (self = [self init]) {
      ······
          [self rotateParentLayer:60];//X 轴旋转60 度
    }
    return self;
}

运行结果如下图:

我去还不是我们想要的。。。

那么我们到最后一步吧。。。。

4、更改继承 CATransformLayer 

@interface KBSpinnyMcSpinface : CATransformLayer

 结束:完美运行。 其实我想说的是老外的创意真的无极限。。。。

(我是参考老外的swift版本翻译过来的:https://medium.com/ios-os-x-development/effervescent-calayer-transfigurations-on-ios-c5e78781db17#.3mrahw54q) 

 

原文地址:https://www.cnblogs.com/kingbo/p/7161544.html