#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
iOS动画高级-图层树
最新推荐文章于 2023-06-25 20:51:27 发布