3.5 IOS 视图的形变(形变属性)、layer层、圆角半径、绘制边框、角度和和弧度之间的转换

UIView的CALayer

一、首先简单的说下UIView的CALayer.
UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
@property(nonatomic,readonly,retain) CALayer *layer;

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示。因此,通过操作这个CALayer对象,可以很方便地调整UIView的一些界面属性,比如:阴影、圆角大小、边框宽度和颜色等。
总结:UIView本身不具备显示的功能,拥有显示功能的是它内部的图层。

clipsToBounds和masksToBounds

clipsToBounds:是类View的属性,如果设置为yes,则不显示超出父View的部分
masksToBounds:是类CALayer的属性,如果设置为yes,则不显示超出父View layer的部分

IOS 视图的形变(形变属性)、layer层、圆角半径、绘制边框、角度和和弧度之间的转换

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self aboutothers];
}

- (void)aboutothers{
    //UIView 的属性
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(40, 40, 100, 100)];
    label.backgroundColor = [UIColor redColor];
    label.text = @"hello";
    label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:label];
    
    //1. 形变属性  会导致内容跟着形变   父变 子也变
    //拉伸形变 sx 表示水平方向拉伸的倍数, sy表示垂直方向拉伸的倍数
    //整数表示正向变    负数表示负方向变
//    label.transform = CGAffineTransformMakeScale(1.5, -0.5);
    //旋转形变 angle 表示旋转的弧度
    label.transform = CGAffineTransformMakeRotation(M_PI);
    label.transform = CGAffineTransformMakeRotation([self degrees:30]);
    //2.layer层
    //layer第一种是用来做视图显示的。
    //layer第二种是用来做动画的。
    //如果要给一个视图绘制圆角,可以通过修改cornerRadius这个属性来实现的。但是,如果一个视图是UILabel或者UIImageView等用来显示内容的视图
    //2.1 圆角半径
    //其实就是在矩形里面画一个内切圆,当半径等于正方形边长的一半时,会和正方形完美内切,
    //大于会怎么样
    label.layer.cornerRadius = 50;//100
/*
 clipsToBounds:是类View的属性,如果设置为yes,则不显示超出父View的部分
 masksToBounds:是类CALayer的属性,如果设置为yes,则不显示超出父View layer的部分
 */
//    label.layer.masksToBounds = YES;
    label.clipsToBounds = YES;    
    //2.2 绘制边框
    //边框在视图内部画的
    label.layer.borderWidth = 5;
    label.layer.borderColor = [UIColor purpleColor].CGColor;
}
// 角度和和弧度之间的转换
// 希望有一个方法:传入一个角度30°,得到一个幅度π/6
- (CGFloat)degrees:(CGFloat)deg{
    CGFloat angle;
    //360°   2PI
    //180°    PI
    //90°     PI/2
    //deg     PI * deg /180.f
    angle = M_PI * deg /180;
    return angle;
}

@end

3.5 IOS 视图的形变(形变属性)、layer层、圆角半径、绘制边框、角度和和弧度之间的转换_第1张图片
视图旋转圆角半径.png

iOS形变之CGAffineTransform视图的形变

image

CGAffineTransform介绍

概述

CGAffineTransform是一个用于处理形变的类,其可以改变控件的平移、缩放、旋转等,其坐标系统采用的是二维坐标系,即向右为x轴正方向,向下为y轴正方向

在UIView中有一个transform属性便是专门用来控制形变的,其使用方法如下

样例素材

在介绍UIView形变的过程中,我们会使用一个UIImageView图片为例,对各动画效果进行演示

@property (nonatomic, strong) UIImageView *demoImageView;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.demoImageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, [[UIScreen mainScreen] bounds].size.width-40, [[UIScreen mainScreen] bounds].size.height-40)];
    self.demoImageView.image = [UIImage imageNamed:@"demo"];
    [self.view addSubview:self.demoImageView];
}

方法介绍
  • CGAffineTransformMakeTranslation实现以初始位置为基准,在x轴方向上平移x单位,在y轴方向上平移y单位
// 格式
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
// 样例
self.demoImageView.transform = CGAffineTransformMakeTranslation(100, 100);

注: 当tx为正值时,会向x轴正方向平移,反之,则向x轴负方向平移;当ty为正值时,会向y轴正方向平移,反之,则向y轴负方向平移

  • CGAffineTransformMakeScale实现以初始位置为基准,在x轴方向上缩放x倍,在y轴方向上缩放y倍
// 格式
CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
// 样例
self.demoImageView.transform = CGAffineTransformMakeScale(2, 0.5);

注: 当sx为正值时,会在x轴方向上缩放x倍,反之,则在缩放的基础上沿着竖直线翻转;当sy为正值时,会在y轴方向上缩放y倍,反之,则在缩放的基础上沿着水平线翻转

  • CGAffineTransformMakeRotation实现以初始位置为基准,将坐标系统时针旋转angle弧度(弧度=π/180×角度,M_PI弧度代表180角度)
// 格式
CGAffineTransformMakeRotation(CGFloat angle)
// 样例
self.demoImageView.transform = CGAffineTransformMakeRotation(M_PI*0.5);

注1: 当angle为正值时,时针旋转坐标系统,反之时针旋转坐标系统

注2: 时针旋转坐标系统的表现形式为对控件进行时针旋转

  • CGAffineTransformTranslate实现以一个已经存在的形变为基准,在x轴方向上平移x单位,在y轴方向上平移y单位
// 格式
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
// 样例
CGAffineTransform transform = CGAffineTransformMakeTranslation(50, 50);
self.demoImageView.transform = CGAffineTransformTranslate(transform, 50, 50);

  • CGAffineTransformScale实现以一个已经存在的形变为基准,在x轴方向上缩放x倍,在y轴方向上缩放y倍
// 格式
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
// 样例
CGAffineTransform transform = CGAffineTransformMakeScale(2, 0.5);
self.demoImageView.transform = CGAffineTransformScale(transform, 2, 1);

  • CGAffineTransformRotate实现以一个已经存在的形变为基准,将坐标系统时针旋转angle弧度(弧度=π/180×角度,M_PI弧度代表180角度)
// 格式
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
// 样例
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI*0.25);
self.demoImageView.transform = CGAffineTransformRotate(transform, M_PI*0.25);

  • 特殊地,transform属性默认值为CGAffineTransformIdentity,可以在形变之后设置该值以还原到最初状态
// 样例
self.demoImageView.transform = CGAffineTransformIdentity;

CGAffineTransform原理

CGAffineTransform形变是通过"仿射变换矩阵"来控制的,其中平移是矩阵相加,旋转与缩放则是矩阵相乘,为了合并矩阵运算中的加法和乘法,引入了齐次坐标的概念,它提供了用矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法.CGAffineTransform形变就是把二维形变使用一个三维矩阵来表示,其中第三列总是(0,0,1),形变通过前两列来控制,系统提供了CGAffineTransformMake结构体来控制形变

// 格式
CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)

该三维变换矩阵如下

image

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

image
image

由此可知,其中tx用来控制在x轴方向上的平移,ty用来控制在y轴方向上的平移;a用来控制在x轴方向上的缩放,d用来控制在y轴方向上的缩放;abcd共同控制旋转

  • 平移CGAffineTransformMakeTranslation原理
self.demoImageView.transform = CGAffineTransformMakeTranslation(100, 100);
self.demoImageView.transform = CGAffineTransformMake(1, 0, 0, 1, 100, 100);

  • 缩放CGAffineTransformMakeScale原理
self.demoImageView.transform = CGAffineTransformMakeScale(2, 0.5);
self.demoImageView.transform = CGAffineTransformMake(2, 0, 0, 0.5, 0, 0);

  • 旋转CGAffineTransformMakeRotation原理
self.demoImageView.transform = CGAffineTransformMakeRotation(M_PI*0.5);
self.demoImageView.transform = CGAffineTransformMake(cos(M_PI * 0.5), sin(M_PI * 0.5), -sin(M_PI * 0.5), cos(M_PI * 0.5), 0, 0);

  • 初始状态CGAffineTransformIdentity原理
self.demoImageView.transform = CGAffineTransformIdentity;
self.demoImageView.transform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);

iOS View的ClipsToBounds属性

在开发终于到了子视图超出父视图的部分不显示。然后就出现了这个

ClipsToBounds
属性了。

简单的说就是,当

ClipsToBounds
属性设置成YES的时,剪裁超出父视图范围的子视图部分。当设置成NO的时候,不剪裁超出父视图范围的子视图。

默认是NO 在scrollView中默认是YES

举个例子:
下面是红色view是蓝色view的子视图 ,父视图(蓝色view)的

ClipsToBounds
设置成NO;


UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(30,200, 200, 40)];
[self.view addSubview:textField];
textField.backgroundColor = [UIColor blueColor];
textField.clipsToBounds = NO;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, 3000, 4)];
[textField addSubview:label];
label.backgroundColor = [UIColor redColor];

效果图如下:

image

ClipsToBounds设置成YES;


UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(30,200, 200, 40)];
[self.view addSubview:textField];
textField.backgroundColor = [UIColor blueColor];
textField.clipsToBounds = YES;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, 3000, 4)];
[textField addSubview:label];
label.backgroundColor = [UIColor redColor];

效果图如下:

image

layer层的masksToBounds属性

我们可以对UIView设置它的圆角
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 120)];
view.backgroundColor = [UIColor blackColor];
view.layer.cornerRadius = 10;
[self.view addSubview:view];
这段代码会按照我们的预想出现圆角效果.
但是当我们往view上面添加一个UILabel或者一个UIButton的时候,下面的代码就不管用了
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 30, 30)];
label.text = @"93";
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor =[UIColor redColor] ;
label.layer.cornerRadius = 15;
[view addSubview:label];
我们需要再设置一个属性,这个label的圆角效果才能出来

你可能感兴趣的:(3.5 IOS 视图的形变(形变属性)、layer层、圆角半径、绘制边框、角度和和弧度之间的转换)