iOS动画高级-图层树

4 篇文章 0 订阅
#import "ViewController.h"

@interface ViewController ()<CALayerDelegate>

@property (weak, nonatomic) IBOutlet UIView *layerView;
@property (weak, nonatomic) IBOutlet UIImageView *hourHand;
@property (weak, nonatomic) IBOutlet UIImageView *minuteHand;
@property (weak, nonatomic) IBOutlet UIImageView *secondHand;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (nonatomic, weak) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    /**
     Core Animation 是一个复合引擎,它的职责就是尽可能快地组合屏幕上不同的可视内容,这个内容被分解成独立的图层,存储在一个叫做图层书的体系中。于是这个树形成了UIKit以及在iOS应用程序当中你所能在屏幕上看见的一切的基础。
     iOS当中,所有的视图都是从一个叫做UIView的基类派生而来的,UIView可以处理触摸时间,可以支持基于Core Craphics绘图,可以做仿射变换(例如旋转或者缩放),或者简答的类似于滑动或者渐变的动画。
     
     实际上不是两个层级关系,而是四个,每个都扮演不同的角色,除了视图成绩和图层树之外,还存在呈现树和渲染树
     
     CALayer 特有功能
     1.阴影、圆角、带颜色的边框 
     2.3D变换 
     3.非矩形范围 
     4.透明遮罩 
     5.多级非线性动画
     
     当满足一下条件的时候,可能更需要使用CALayer而不是UIView 
     
     1.开发同时可以在Mac OS上运行的跨平台应用 
     2.使用多种CALayer的子类,并且不想创建二外的UIView去包装他们所有
     做一些对性能特别挑剔的工作,比如对UIView一些可忽略不计的操作都会引起显著的不同(尽管如此,你可能会直接想使用OpenGL绘图)
     
     如果不需要寄宿图,那么就不要创建drawRect:方法了,这会造成CPU资源和内存的浪费,这也是为什么苹果建议:如果没有自定义绘制的任务就不要在子类中写一个空的-drawRect:方法 
     
     UIView三个比较重要的布局属性:frame,bounds和center,CALayer 
     CALayer对应的是frame,bounds和position 
     
     坐标系 
     和视图一样,图层在图层树当中也是相对于父图层按层级关系放置,一个图层的position依赖于它的父视图的bounds,如果图层发生了移动,它的所有子视图也会跟着移动。 
     
     我们希望在真实的应用中也能显示出绘图的顺序,同样的,如果我们提高绿色视图zPosition,我们会发现顺序发了,其实并不需要增加太多,视图都非常地薄,所以给zPosition提高一个像素就可以让绿色视图前置,当然0.1或者0.0001也能够做到,最好不要这样,因为浮点类型四舍五入计算可能会造成一些不便的麻烦
     
     */
    
    // create subLayer
    CALayer *blueLayer = [CALayer layer];
    blueLayer.frame = CGRectMake(50, 50, 100, 100);
    blueLayer.backgroundColor = [UIColor blueColor].CGColor;
    
    blueLayer.delegate = self;
    
    // add it to our view
     [self.layerView.layer addSublayer:blueLayer];
    
    UIImage *image = [UIImage imageNamed:@"man_page.png"];
    
    self.layerView.layer.contents = (__bridge id _Nullable)(image.CGImage);
    
    /**
     CA_EXTERN NSString * const kCAGravityCenter
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityTop
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityBottom
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityLeft
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityRight
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityTopLeft
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityTopRight
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityBottomLeft
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityBottomRight
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityResize
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityResizeAspect
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
     CA_EXTERN NSString * const kCAGravityResizeAspectFill
     CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);

     */
    self.layerView.layer.contentsGravity = kCAGravityResizeAspect;
    self.layerView.layer.contentsScale = [UIScreen mainScreen].scale;
    self.layerView.layer.masksToBounds = YES;
    
    // 允许在图层边框里显示寄宿图的一部分
    // self.layerView.layer.contentsRect = CGRectMake(0, 0, 0.5, 0.5);
    self.layerView.layer.contentsCenter = CGRectMake(0.25, 0.25, 0.5, 0.5);
    
    // force layer to redraw
    [blueLayer display];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
    self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
    self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
    //start timer
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(tick) userInfo:nil repeats:true];
    //set initial hand positions
    [self tick];
    
    
    //  move the green view zPosition nearer to the camera
    self.greenView.layer.zPosition = 1.0f;
}

- (void)tick
{
    // convert time to hours, minutes and seconds
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSUInteger units = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
    CGFloat hoursAngle = (components.hour / 12.0) * M_PI * 2.0;
    
    CGFloat minsAngle = (components.minute / 60.0) * M_PI * 2.0;
    // calculate second hand angle
    CGFloat secsAngle = (components.second / 60.0) * M_PI * 2.0;
    // rotate hands
    self.hourHand.transform = CGAffineTransformMakeRotation(hoursAngle);
    self.minuteHand.transform = CGAffineTransformMakeRotation(minsAngle);
    self.secondHand.transform = CGAffineTransformMakeRotation(secsAngle);
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    
    // draw a thick red circle
    CGContextSetLineWidth(ctx, 10);
    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextStrokeEllipseInRect(ctx, layer.bounds);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值