zoukankan      html  css  js  c++  java
  • 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) 

     

  • 相关阅读:
    iOS-修改导航栏文字字体和颜色
    iOS-cocoapods使用方法
    iOS-创建UIScrollerView(封装UIScrollerView)
    iOS-根据两个经纬度计算相距距离
    iOS-JS调用OC代码
    iOS-tableView刷新指定行,组
    雷赛dmc2410控制卡,驱动器 光栅 加电机
    做自己的类库dll文件
    Sender
    BackGroundWorker控件的使用注意
  • 原文地址:https://www.cnblogs.com/kingbo/p/7161544.html
Copyright © 2011-2022 走看看