ios開發核心動畫三:隱式動畫與時鐘效果

一:隱式動畫oop

#import "ViewController.h"

@interface ViewController ()

/** <#註釋#> */
@property (nonatomic, weak)  CALayer *layer;
@property (weak, nonatomic) IBOutlet UIView *redView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    
    
    CALayer *layer = [CALayer layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.frame = CGRectMake(50, 50, 100, 100);
    self.layer = layer;
    [self.view.layer addSublayer:layer];
    
    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    //只有非根層纔有隱式動畫,(本身手動建立的圖片)
    [CATransaction begin];
    [CATransaction setDisableActions:NO];//此屬性可設置關掉隱士動畫
    [CATransaction setAnimationDuration:5];
    self.layer.backgroundColor = [UIColor greenColor].CGColor;
    [CATransaction commit];
    
    self.layer.bounds = CGRectMake(0, 0, 90, 90);
    self.layer.backgroundColor = [UIColor greenColor].CGColor;
    self.layer.position = CGPointMake(100, 400);
    
    
    self.redView.layer.position = CGPointMake(300, 400);
    self.redView.layer.bounds = CGRectMake(0, 0, 100, 100);
    self.redView.layer.backgroundColor = [UIColor greenColor].CGColor;
    
}


@end

 

什麼是隱式動畫?動畫

瞭解什麼是隱式動畫前,要先了解是什麼根層和非根層.atom

根層:UIView內部自動關聯着的那個layer咱們稱它是根層.spa

非根層:本身手動建立的層,稱爲非根層.code

 

隱式動畫就是當對非根層的部分屬性進行修改時, 它會自動的產生一些動畫的效果.component

咱們稱這個默認產生的動畫爲隱式動畫.orm

 

如何取消隱式動畫?blog

首先要了解動畫底層是怎麼作的.動畫的底層是包裝成一個事務來進行的.事件

什麼是事務?圖片

不少操做綁定在一塊兒,當這些操做執行完畢後,纔去執行下一個操做.

 

開啓事務

[CATransaction begin];

設置事務沒有動畫

[CATransaction setDisableActions:YES];

設置動畫執行的時長

[CATransaction setAnimationDuration:2];

 提交事務

 [CATransaction commit];

 

二:時鐘效果:

效果如圖:

#import "ViewController.h"

//每一秒旋轉的度數
#define perSecA 6

//每一分旋轉的度數
#define perMinA 6

//每一小時旋轉的度數
#define perHourA 30

//每一分,時針旋轉的度數
#define perMinHour 0.5


#define angle2Rad(angle) ((angle) / 180.0 * M_PI)

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *colockView;

/** 當前的秒針 */
@property (nonatomic, weak)   CALayer *secL;
/** 當前的分針 */
@property (nonatomic, weak)   CALayer *minL;
/** 當前的針針 */
@property (nonatomic, weak)   CALayer *hourL;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //添加時針
    [self setHour];
    
    //添加分針
    [self setMin];
    //添加秒針
    [self setSec];
    
    
    //添加定時器:scheduledTimerWithTimeInterval不用加到runLoop,由於已經默認添加到了runLoop
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    //添加的定時器不會當即執行,而是過一秒纔會執行,此時能夠調用定時器的fire方法,當即執行,也能夠手動調用定時器的方法
    [self timeChange];
}

//第一稱調用一次
- (void)timeChange {
    
    
    
    NSCalendar *cal = [NSCalendar currentCalendar];
    //components:日曆的組件,年,月,日 ,時,分,秒.
    //fromDate:從什麼時間開始獲取
    NSDateComponents *cmp = [cal components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour  fromDate:[NSDate date]];
    //獲取當前多少秒
    NSInteger curSec = cmp.second + 1;
    
    
    //秒針開始旋轉
    //計算秒針當前旋轉的角度.
    //angle  = 當前多少秒 * 每一秒旋轉多少度.
    /**
     *    CATransform3DMakeRotation:3D旋轉:1:必須是在layear層才能進行3D旋轉,用transform,旋轉的角度爲弧度制,2:#define angle2Rad(angle) ((angle) / 180.0 * M_PI) 3:分xyz軸,
     */
    CGFloat secA = curSec * perSecA;
    self.secL.transform = CATransform3DMakeRotation(angle2Rad(secA), 0, 0, 1);
    
    
    //獲取當前多少秒
    NSInteger curMin = cmp.minute;
    NSLog(@"%ld",curMin);
    //分針開始旋轉
    //計算分針當前旋轉的角度.
    //angle  = 當前多少分 * 每一分旋轉多少度.
    CGFloat minA = curMin * perMinA;
    self.minL.transform = CATransform3DMakeRotation(angle2Rad(minA), 0, 0, 1);
    
    //獲取當前是多少小時
    NSInteger curHour = cmp.hour;
    NSLog(@"%ld",curMin);
    //分針開始旋轉
    //計算分針當前旋轉的角度.
    //angle  = 當前多少小時 * 每一小時旋轉多少度.
    CGFloat hourA = curHour * perHourA + curMin * perMinHour;
    self.hourL.transform = CATransform3DMakeRotation(angle2Rad(hourA), 0, 0, 1);
    
    
}

/**
 *  1:搭建時針秒針分針的UI效果:1:UIView和CALayear是同樣的效果,可是UIView比CALyear多了一個處理點擊事件,則CALyear相對於UIView來講更加輕量級,更加高效 2:非根層的layear也就是本身建立的layear都存在隱士動畫,要關閉隱式動畫,用動畫事物CATransaction去關閉:
    開啓事務
 
    [CATransaction begin];
 
    設置事務沒有動畫
 
    [CATransaction setDisableActions:YES];
 
    設置動畫執行的時長
 
    [CATransaction setAnimationDuration:2];
 
    提交事務
 
    [CATransaction commit];
 
  3:不管是旋轉,縮放都是繞着錨點進行的.也就是默認狀況下是繞着中心點center進行的。因此要改變其繞着最後的節點旋轉,須要先定義好layear的position,在定義錨點,最後的效果是錨點與point點重合。position的位置爲錶盤的中心點,錨點的默認位置爲0.5 ,0.5,修改錶盤的錨點位置讓錨點與position點重合,這樣旋轉的時候就會繞着錨點旋轉。再把此layear添加到錶盤的layear上。
 *
 *
 */

//添加秒針
//不管是旋轉,縮放都是繞着錨點進行的.
- (void)setSec {
    
    CALayer *secL = [CALayer layer];
    secL.bounds = CGRectMake(0, 0, 1, 80);
    secL.backgroundColor = [UIColor redColor].CGColor;
    secL.anchorPoint = CGPointMake(0.5, 1);
    secL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
    [self.colockView.layer addSublayer:secL];
    self.secL = secL;
    
}

//添加分針
- (void)setMin {
    
    CALayer *minL = [CALayer layer];
    minL.bounds = CGRectMake(0, 0, 3, 70);
    minL.backgroundColor = [UIColor blackColor].CGColor;
    minL.anchorPoint = CGPointMake(0.5, 1);
    minL.cornerRadius = 1.5;
    minL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
    [self.colockView.layer addSublayer:minL];
    self.minL = minL;
    
}

//時針
- (void)setHour {
    
    CALayer *hourL = [CALayer layer];
    hourL.bounds = CGRectMake(0, 0, 3, 50);
    hourL.backgroundColor = [UIColor blackColor].CGColor;
    hourL.anchorPoint = CGPointMake(0.5, 1);
    hourL.cornerRadius = 1.5;
    hourL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
    [self.colockView.layer addSublayer:hourL];
    self.hourL = hourL;
    
}




//-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//
//    //全部旋轉,縮放,都是繞着錨點進行.
//    self.secL.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
//}

@end

1.搭建界面.

分析界面.

界面上時針,分針,秒針不須要與用戶進行交互.因此均可以使用layer方式來作.

作以前要觀察時針在作什麼效果.

是根據當前的時間,繞着錶盤的中心點進行旋轉.

要了解一個很是重要的知識點.不管是旋轉,縮放它都是繞着錨點.進行的.

 

要想讓時針,分針,稱針顯示的中間,還要繞着中心點進行旋轉.

那就要設置它的position和anchorPoint兩個屬性.

 

 

建立秒針

    CALayer *layer = [CALayer layer];

    _secLayer = layer;

    layer.bounds = CGRectMake(0, 0, 1, 80);

    layer.anchorPoint = CGPointMake(0.5, 1);

    layer.position = CGPointMake(_clockView.bounds.size.width * 0.5, _clockView.bounds.size.height * 0.5);

    layer.backgroundColor = [UIColor redColor].CGColor;

    [_clockView.layer addSublayer:layer];

   

   

2.讓秒針開始旋轉.

 

讓秒針旋轉.因此要計算當前的旋轉度是多少?

當前的旋轉角度爲:當前的時間 * 每秒旋轉多少度.

 

計算每一秒旋轉多少度.

60秒轉一圈360度

360 除以60就是每一秒轉多少度.每秒轉6度.

 

獲取當前的時間

建立日曆類

        NSCalendar *calendar = [NSCalendar currentCalendar];

        把日曆類轉換成一個日期組件

        日期組件(年,月,日,時,分,秒)

        component:日期組件有哪些東西組成,他是一個枚舉,裏面有年月日時分秒

        fromDate:當前的日期

        NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond

            fromDate:[NSDate date]];

            

        咱們的秒就是保存在日期組件裏面,它裏面提供了不少get方法.

        NSInteger second = cmp.second;

         

        那麼當前秒針旋轉的角度就是

        當前的秒數乘以每秒轉多少度.

        second * perSecA 

        還得要把角度轉換成弧度.

        

        由於下面分針,時針也得要用到, 就把它抽出一個速參數的宏.

        #define angle2Rad(angle) ((angle) / 180.0 * M_PI)

        

        讓它每隔一秒旋轉一次.因此添加一個定時器.

        每一個一秒就調用,旋轉秒針

         - (void)timeChange{

         獲取當前的秒數

         建立日曆類

         NSCalendar *calendar = [NSCalendar currentCalendar];

         把日曆類轉換成一個日期組件

         日期組件(年,月,日,時,分,秒)

         component:日期組件有哪些東西組成,他是一個枚舉,裏面有年月日時分秒

         fromDate:當前的日期

         NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond 

             fromDate:[NSDate date]];

         咱們的秒就是保存在日期組件裏面,它裏面提供了不少get方法.

         NSInteger second = cmp.second;

         秒針旋轉多少度.

         CGFloat angel = angle2Rad(second * perSecA);

         旋轉秒針

         self.secondL.transform = CATransform3DMakeRotation(angel, 0, 0, 1);

         }

        運行發現他會一下只就調到某一個時間纔開始旋轉

        一開始的時候就要來到這個方法,獲取當前的秒數把它定位好.

        要在添加定時器以後就調用一次timeChange方法.

        

 

3.添加分針

 

快速拷貝一下,而後添加一個分針成員屬性.

        修改寬度,修改顏色

        也得要讓它旋轉,

        要算出每分鐘轉多少度

        轉60分鐘恰好是一圈

        因此每一分鐘也是轉6度.

        

        獲取當前多少分?

        一樣是在日期組件裏面得到

        裏面有左移符號,右移符號.他就能夠用一個並運算

        如今同時讓他支持秒數和分 後面直接加上一個 |

         NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond | 

         NSCalendarUnitMinute 

         fromDate:[NSDate date]];

         

        CGFloat minueteAngel = angle2Rad(minute * perMinuteA);

        self.minueL.transform = CATransform3DMakeRotation(minueteAngel, 0, 0, 1);

 

4.添加時針

 

  一樣複製以前的,添加一個小時屬性

         小時轉多少度

         當前是多少小時,再計算先每一小時轉多少度.

         12個小時轉一圈. 360除以12,每小時轉30度

         時針旋轉多少度

         CGFloat hourAngel = angle2Rad(hour * perHourA);

         旋轉時針

         self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);

            

        直接這樣寫會有問題

        就是沒轉一分鐘,小時也會移動一點點

        接下來要算出,每一分鐘,小時要轉多少度

        60分鐘一小時.一小時轉30度.

        30 除以60,就是每一分鐘,時針轉多少度.0.5

 

        時針旋轉多少度

        CGFloat hourAngel = angle2Rad(hour * perHourA + minute * perMinuteHourA);

        旋轉時針

        self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);

相關文章
相關標籤/搜索