美文网首页
iOS核心动画(二)

iOS核心动画(二)

作者: Rathen | 来源:发表于2017-11-26 10:00 被阅读24次

图层几何学

主要介绍图层内部是如何根据付图层和兄弟图层来控制位置和尺寸,还有如何管理图层的几何结构,以及它是如何被自动调整和自动布局影响的。

布局

UIView有三个比较重要的布局属性frameboundscenter
CALayer对应的叫做frameboundsposition.
frame代表了图层的外部坐标(也就是在父图层上占据的空间)
bounds是内部坐标({0,0}是图层的左上角)
center、position都代表了相对于父图层anchorPoint所在的位置。

UIView和CALayer的坐标系.png
操纵视图的frame,实际上是改变视图下CALayer的frame。

锚点

图层的anchorPoint通过position来控制它的frame的位置,你可以认为anchorPoint是用来移动图层的把柄。
anchorPoint用单位坐标来描述,也就是图层的相对坐标,图层左上角是{0,0},右下角是{1,1},默认坐标是{0.5,0.5}

OC代码
#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIView *secondHandView;
@property (nonatomic, strong) UIView *minuteHandView;
@property (nonatomic, strong) UIView *hourHandView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CALayer *layer = [[CALayer alloc] init];
    layer.bounds = CGRectMake(0, 0, 150, 150);
    layer.position = self.view.center;
    UIImage *image = [UIImage imageNamed:@"clock"];
    layer.contents = (__bridge id)image.CGImage;
    [self.view.layer addSublayer:layer];
    
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(clockRun)];
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
    
}

- (void)clockRun {
    
    
    NSTimeZone *tZone = [NSTimeZone localTimeZone];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *currentDate = [NSDate date];
    [calendar setTimeZone:tZone];
    
    NSDateComponents *currentTime = [calendar components:NSCalendarUnitSecond|NSCalendarUnitMinute|NSCalendarUnitHour|NSCalendarUnitTimeZone fromDate:currentDate];
    CGFloat angle =  (M_PI * 2 / 60) * currentTime.second;
    
    self.secondHandView.transform = CGAffineTransformMakeRotation(angle);
    
    CGFloat minuteAngle = (M_PI * 2 / 60) * currentTime.minute;
    self.minuteHandView.transform = CGAffineTransformMakeRotation(minuteAngle);
    
    CGFloat hourAngle = (M_PI * 2 / 12) *currentTime.hour;
    self.hourHandView.transform = CGAffineTransformMakeRotation(hourAngle);
    
    
    
}

- (UIView *)secondHandView {
    if (_secondHandView == nil) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor redColor];
        view.bounds = CGRectMake(0, 0, 1, 60);
        view.center = self.view.center;
        view.layer.anchorPoint = CGPointMake(0.5, 1);
        [self.view addSubview:view];
        _secondHandView = view;
    }
    return _secondHandView;
}

- (UIView *)minuteHandView {
    if (_minuteHandView == nil) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor grayColor];
        view.bounds = CGRectMake(0, 0, 2, 60);
        view.center = self.view.center;
        view.layer.anchorPoint = CGPointMake(0.5, 1);
        [self.view addSubview:view];
        _minuteHandView = view;
    }
    return _minuteHandView;
}

- (UIView *)hourHandView {
    if (_hourHandView == nil) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor blackColor];
        view.bounds = CGRectMake(0, 0, 3, 60);
        view.center = self.view.center;
        view.layer.anchorPoint = CGPointMake(0.5, 1);
        [self.view addSubview:view];
        _hourHandView = view;
    }
    return _hourHandView;
}


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

Swift代码
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let layer = CALayer()
        layer.bounds = CGRect(x: 0, y: 0, width: 150, height: 150)
        layer.position = self.view.center
        let image = UIImage(named:"clock")
        layer.contents = image?.cgImage
        view.layer .addSublayer(layer)
        
        let link = CADisplayLink(target: self, selector: #selector(clockRun))
        //将创建的CADisplayLink加入到主线程中
        link.add(to: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
        
        
    }
    
   @objc private func clockRun()   {
        let tZone = NSTimeZone.local
        var calendar = NSCalendar.current
        let currentDate = Date()
        calendar.timeZone = tZone
        
        let currentTime = calendar.dateComponents([Calendar.Component.hour,Calendar.Component.minute,Calendar.Component.second], from: currentDate)
        //设置秒针
        let angle = Double(currentTime.second!) * (Double.pi * 2 / 60);
        secondHandView.transform = CGAffineTransform(rotationAngle: CGFloat(angle));
        
        //设置分针
        let minuteAngle = Double (currentTime.minute!) * (Double.pi * 2.0 / 60)
        
        minuteHandView.transform = CGAffineTransform(rotationAngle: CGFloat(minuteAngle))
        
        //设置时针
        let hourAngle = Double (currentTime.hour!) * (Double.pi * 2.0 / 12)
        
        hourHandView.transform = CGAffineTransform(rotationAngle: CGFloat(hourAngle))
    }
    
    //秒针
    lazy var secondHandView : UIView = {
        let secondHandView = UIView();
        secondHandView.backgroundColor = UIColor.red
        secondHandView.bounds = CGRect(x: 0, y: 0, width: 1, height: 60)
        //修改锚点
        secondHandView.center = view.center;
        secondHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
       view.addSubview(secondHandView)
        return secondHandView;
    }()
    
    lazy var minuteHandView : UIView = {
        //设置分针针
        let minuteHandView = UIView()
        minuteHandView.backgroundColor = UIColor.gray
        minuteHandView.bounds = CGRect(x: 0, y: 0, width: 2, height: 60)
        //修改锚点
        minuteHandView.center = view.center;
        minuteHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
        view.addSubview(minuteHandView)
        return minuteHandView
    }()
    //时针
    lazy var hourHandView : UIView = {
        //设置时针
        let hourHandView = UIView()
        hourHandView.backgroundColor = UIColor.black
        hourHandView.bounds = CGRect(x: 0, y: 0, width: 3, height: 60)
        //修改锚点
        hourHandView.center = view.center;
        hourHandView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
        view.addSubview(hourHandView)
        return hourHandView
    }()

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

1.png

坐标系

和视图一样,图层在图层树中也是相当于父图层按照层级关系放置,一个层级的position依赖于它的父层级的bounds,如果父图层发生的变化,它所有的子图层都会移动。
和UIView严格的二维坐标不同,CALayer存在于一个三维k空间当中。除了我们讨论过的position和anchorPoint属性外,CALayer还有两个属性zPosition和anchorPointZ,二者都是在Z轴上描述图层位置的浮点类型。

相关文章

网友评论

      本文标题:iOS核心动画(二)

      本文链接:https://www.haomeiwen.com/subject/sricbxtx.html