UI基础 - CGAffineTransform | UIView动画

▶ CGAffineTransform

1 - CGAffineTransform 是一个用于处理形变的类,可以改变控件的平移、缩放、旋转等;它的坐标系统采用的是二维坐标系:向右为 x轴 正方向,向下为 y轴 正方向;它的形变是通过仿射变换矩阵来控制的:其中平移是矩阵相加;旋转与缩放则是矩阵相乘

2 - 为了合并矩阵运算中的加法和乘法,引入了齐次坐标的概念:它提供了用矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法!CGAffineTransform 形变就是把二维形变使用一个三维矩阵来表示,其中第三列总是 (0,0,1),形变通过前两列来控制

CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)

通过变换矩阵左乘向量,将空间中的一个点集从一个坐标系变换到另一个坐标系中,计算方式如下

其中 tx 用来控制在 x轴 方向上的平移;ty 用来控制在 y轴 方向上的平移

a 用来控制在 x轴 方向上的缩放;d 用来控制在 y轴 方向上的缩放

abcd 共同控制旋转

3 - 代码示例:仿射变换的基本使用

 1 #import "ViewController.h"
 2 @implementation ViewController
 3 - (void)viewDidLoad {
 4     [super viewDidLoad];
 5     self.view.backgroundColor = [UIColor cyanColor];
 6     self.title = @"CGAffineTransform";
 7 
 8     // Btn 按钮
 9     UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
10     btn.frame = CGRectMake(50, 90, self.view.frame.size.width - 100, 30);
11     [btn setTitle:@"点我变换" forState:UIControlStateNormal];
12     btn.layer.cornerRadius = 6;
13     [btn setTitle:@"松开我" forState:UIControlStateHighlighted];
14     btn.backgroundColor = [UIColor redColor];
15     [btn addTarget:self action:@selector(doTransfrom) forControlEvents: UIControlEventTouchUpInside ];
16     [self.view addSubview:btn];
17     
18     // 图片
19     UILabel *lab = [[UILabel alloc] init];
20     lab.frame = CGRectMake(80, 150, self.view.frame.size.width - 160, 220) ;
21     lab.text = @"---我是背景文案---";
22     lab.textAlignment = NSTextAlignmentCenter;
23     lab.tag = 1000;
24     lab.backgroundColor = [UIColor whiteColor];
25     [self.view addSubview:lab];
26 }
27 
28 // 旋转
29 - (void)doTransfrom{
30     UILabel *aView = (UILabel *)[self.view viewWithTag:1000];
31     
32 //-------------  测试一:旋转  -------------
33 //    // 当弧度为正值时,顺时针旋转;反之逆时针旋转
34 //    // CGAffineTransformMakeRotation 以初始位置为基准
35 //    aView.transform = CGAffineTransformMakeRotation(M_PI / 4);
36 //
37 ////    // CGAffineTransformRotate:以一个已经存在的形变为基准
38 ////    aView.transform = CGAffineTransformRotate(aView.transform, M_PI_4);
39 //
40 //    // CGAffineTransformIdentity:可以在形变之后设置该值以还原到最初状态
41 //    // 开启动画:验证在形变后还原到初始状态
42 //    [UIView beginAnimations:nil context:nil];
43 //    [UIView setAnimationDuration:1.5];
44 //    aView.transform = CGAffineTransformIdentity;
45 //    // aView.transform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);// 原始值
46 //    [UIView commitAnimations];
47 
48 //-------------  测试二:缩放  -------------
49 //    // CGAffineTransformMakeScale
50 //    // 实现以初始位置为基准,在 x轴 方向上缩放 x 倍,在 y轴 方向上缩放 y 倍
51 //    // 当 x 为正值时,会在 x轴 方向上缩放 x 倍。反之,则在缩放的基础上沿着竖直线翻转
52 //    // 当 y 为正值时,会在 y轴 方向上缩放 y 倍。反之,则在缩放的基础上沿着水平线翻转
53 //    aView.transform = CGAffineTransformMakeScale(-0.8, -0.8);
54 //
55 ////    // CGAffineTransformScale 以一个已经存在的形变为基准
56 ////    aView.transform = CGAffineTransformScale(aView.transform, 0.9, 0.9);
57 
58 //-------------  测试三:平移  -------------
59     // CGAffineTransformMakeTranslation
60     // 实现以初始位置为基准,在 x 轴方向上平移 x 单位,在 y 轴方向上平移 y 单位
61     aView.transform = CGAffineTransformMakeTranslation(20,-30);// 右上
62     
63 //    // CGAffineTransformTranslate 以一个已经存在的形变为基准
64 //    aView.transform = CGAffineTransformTranslate(aView.transform,20,-30);
65 }
66 @end

▶ UIView动画

1 - iOS 中动画主要分为 UIView动画 和 CALayer动画;UIView动画本质上也是 CALayer动画;UIView动画分为 UIView属性动画 和 UIViewTransition动画

2 - UIView属性动画:其动画属性有 frame、center、bounds、alpha、transform、backgroundColor... 

3 - 动画方法

// 如果两个动画发生在同一个 View 中,且前一个动画还未结束而后一个动画就开始进行的情况下
// 该方法会将动画运行的当前状态作为下一个状态的开始状态,这样就避免了动画跳跃的不连贯问题
[UIView setAnimationBeginsFromCurrentState:YES];

动画的实现除了可由动画块实现外,也可以使用 block

4 - UIViewTransition

过渡给 UIView动画块 添加了视觉表现力

// cache 参数告诉系统是否用 Cache 进行动画(与硬件相关),一般填 yes
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;

过渡效果在 UIKit 中封装了 4 种效果

typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,  // 从左向右旋转
    UIViewAnimationTransitionFlipFromRight, // 从右向左旋转
    UIViewAnimationTransitionCurlUp,        // 向上翻页
    UIViewAnimationTransitionCurlDown,      // 向下翻页
};

5 - 代码示例

A. UIView动画块

// - ViewController.m

 1 #import "ViewController.h"
 2 @interface ViewController ()
 3 @property(nonatomic,strong)UILabel *animationView; // 要执行的动画 UI
 4 @property(assign,nonatomic)CGRect frameDemo;       // 记录动画视图 初始frame
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11     
12     // 动画
13     self.animationView = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 100, 40)];
14     self.animationView.text = @"属性动画";
15     self.animationView.textAlignment = NSTextAlignmentCenter;
16     self.animationView.textColor = [UIColor blackColor];
17     self.animationView.backgroundColor = [UIColor redColor];
18     [self.view addSubview:self.animationView];
19     self.frameDemo = self.animationView.frame;
20     
21     // 动画块:开启动画(beginAnimations)到提交动画(commitAnimations)之间的代码
22     
23     // 开启动画---------------------------
24     [UIView beginAnimations:@"animation01" context:@"看看是啥"];
25     [UIView setAnimationDelay:1.0];    // 延迟
26     [UIView setAnimationDelegate:self];// 设置代理:可以监控动画的开始和结束
27     
28     // 也可以定义一个方法使其成为代理方法
29     // 它会覆盖自身相应的代理方法
30     //[UIView setAnimationDidStopSelector:@selector(animationFinished:)];
31     
32     [UIView setAnimationDuration:3.0]; // 动画时间:1 ~ 2 秒为宜
33     [UIView setAnimationRepeatCount:2];// 重复次数
34     [UIView setAnimationRepeatAutoreverses:YES];// 动画反弹
35     [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];// 过渡曲线
36     
37     // 影响动画的属性
38     self.animationView.frame = CGRectMake(120, 350, 100, 40);
39     self.animationView.alpha = 0.1;
40     self.animationView.backgroundColor = [UIColor yellowColor];
41     self.animationView.backgroundColor = [UIColor greenColor];
42     self.animationView.transform = CGAffineTransformMakeRotation(M_PI);
43     
44     // 提交动画--------------------------------
45     [UIView commitAnimations];
46 }
47 
48 - (void)animationFinished:(id)sender{
49     NSLog(@"animation01  DidEnd");
50 }
51 
52 #pragma mark - 代理方法
53 // 开始
54 -(void)animationWillStart:(NSString *)animationID context:(void *)context{
55     if ([animationID isEqualToString:@"animation01"]) {
56         NSLog(@"animation01 will start--%@",context);
57     }
58 }
59 
60 // 结束:finished 参数很重要,我们可以用来判断动画是否是正常结束(正常返回 1,否则返回 0)
61 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
62     
63     // UIView动画:如果 frame 发生改变,动画结束后它不会恢复倒初始位置
64     // 恢复原来的 frame
65     self.animationView.frame = self.frameDemo;
66     self.animationView.alpha = 1.0f;
67 }
68 
69 @end

过渡曲线有四种方式

1  UIViewAnimationCurveEaseInOut // 淡入淡出效果最为自然,也是默认效果
2  UIViewAnimationCurveEaseIn          
3  UIViewAnimationCurveEaseOut    
4  UIViewAnimationCurveLinear

B. block动画

// - ViewController.m

 1 #import "ViewController.h"
 2 @interface ViewController ()
 3 @property(nonatomic,strong)UILabel *animationView;
 4 @property(assign,nonatomic)CGRect frame;
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11     
12     // 动画视图
13     self.animationView = [[UILabel alloc] initWithFrame:CGRectMake(100, 120, 40, 200)];
14     self.animationView.text = @"block动画";
15     self.animationView.textAlignment = NSTextAlignmentCenter;
16     self.animationView.textColor = [UIColor blackColor];
17     self.animationView.backgroundColor = [UIColor redColor];
18     [self.view addSubview:self.animationView];
19     self.frame = self.animationView.frame;
20     
21 //--------------------  UIView动画:缩放
22 //    [UIView beginAnimations:nil context:nil];
23 //    [UIView setAnimationDuration:2.0f];
24 //    self.animationView.transform = CGAffineTransformMakeScale(1.2, 1.2);
25 //    // catch:第二次翻转时会从内存中取,效率较高
26 //    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.animationView cache:YES];
27 //    [UIView commitAnimations];
28     
29 //--------------------------- Block动画
30 //    [UIView animateWithDuration:5.0 animations:^{
31 //        [UIView setAnimationRepeatCount:2];
32 //        [UIView setAnimationRepeatAutoreverses:YES];
33 //        self.animationView.frame = CGRectMake(120, 400, 100, 80);
34 //        self.animationView.backgroundColor = [UIColor blackColor];
35 //    }];
36     
37 //--------------------------- Block动画:弹簧效果
38 //    // usingSpringWithDamping:弹簧力度,值越小越弹动越快
39 //    [UIView animateWithDuration:1.0 delay:0 usingSpringWithDamping:0.1f initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
40 //        CGRect rect = self.animationView.frame;
41 //        rect.origin.y += 150;
42 //        self.animationView.frame = rect;
43 //    } completion:^(BOOL finished){
44 //        self.animationView.backgroundColor = [UIColor yellowColor];
45 //    }];
46     
47     
48 //--------------------------- Block动画:动画嵌套
49 //    // 第一层
50 //    [UIView animateWithDuration:2.0 animations:^{
51 //        self.animationView.frame = CGRectMake(120, 400, 80, 80);
52 //        self.animationView.backgroundColor = [UIColor blackColor];
53 //    } completion:^(BOOL finished){
54 //
55 //        NSLog(@"%@",finished ? @"YES" : @"NO");
56 //        self.animationView.frame = self.frame;
57 //        self.animationView.backgroundColor = [UIColor greenColor];
58 //
59 //        // 第二层
60 //        [UIView animateWithDuration:2.0 animations:^{
61 //            self.animationView.transform =CGAffineTransformRotate(self.animationView.transform, M_PI);
62 //        } completion:^(BOOL finished) {
63 //            [UIView animateWithDuration:2.0 animations:^{
64 //                self.animationView.alpha = 0.3;
65 //            }];
66 //        }];
67 //    }];
68     
69 //--------------------------- 动画嵌套
70     // 第一层
71     [UIView transitionWithView:self.animationView duration:2.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
72         // y 下移 100
73         CGRect rect = self.animationView.frame;
74         rect.origin.y += 100;
75         self.animationView.frame = rect;
76     } completion:^(BOOL finished) {
77         
78         // 第二层:UIView动画块
79         [UIView beginAnimations:nil context:nil];
80         CGRect rect = self.animationView.frame;
81         [UIView setAnimationDuration:2.0];
82         // y 上移 100
83         rect.origin.y -= 100;
84         self.animationView.frame = rect;
85         [UIView commitAnimations];
86     }];
87 }
88 
89 @end

 

posted on 2018-04-10 15:41  低头捡石頭  阅读(20)  评论(0编辑  收藏  举报

导航