美文网首页iOS 深度好文iOS开发深度好文程序员
UIView的transform属性使用--CGAffineTr

UIView的transform属性使用--CGAffineTr

作者: 小白进城 | 来源:发表于2017-07-20 09:25 被阅读126次

    一、CGAffineTransform介绍

    CGAffineTransform可以使控件的产生移动、缩放、旋转效果,其坐标系统采用的是二维坐标系,坐标原点为屏幕的左上角,向右为x轴正方向,向下为y轴正方向。


    二、方法介绍

    下面以使用一个UIImageView图片为例,结合UIView动画、手势进行演示

    @property(strong,nonatomic)UIImageView *imageView;
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self.view addSubview:self.imageView];
    }
    
    -(UIImageView *)imageView{
        if (_imageView==nil) {
            _imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"aa"]];
            _imageView.frame = CGRectMake(0, 0, 100, 80);
        }
        return _imageView;
    }
    

    • 移动控件

    1、CGAffineTransformMakeTranslation实现以初始位置为基准,在x轴方向上平移x单位,在y轴方向上平移y单位

    // 格式
    CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
    // 使用       将图片左(100px)下(150px)方向移动
    CGAffineTransform transform = CGAffineTransformMakeTranslation(-100, 150);
    self.imageView.transform = transform;
    

    2、CGAffineTransformTranslate在已有的transform基础上,增加 移动 效果

    // 格式  
    CGAffineTransformTranslate(CGAffineTransform t,
      CGFloat tx, CGFloat ty)
    // 使用
    self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, -50, 150); 
    

    • 缩放控件

    1、CGAffineTransformMakeScale实现以初始位置为基准,在x轴方向上缩放x倍,在y轴方向上缩放y倍

    // 格式       tx,ty表示的是倍数
    CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
    // 使用       将图片放大2倍
    self.imageView.transform = CGAffineTransformMakeScale(2, 2);
    

    2、CGAffineTransformScale在已有的transform基础上,增加 缩放 效果

    // 格式  
    CGAffineTransformScale(CGAffineTransform t,
      CGFloat sx, CGFloat sy)
    // 使用       宽度缩小一倍,高度拉伸1.5倍
    self.imageView.transform = CGAffineTransformScale(self.imageView.transform, 0.5 1.5); 
    

    • 旋转控件

    1、CGAffineTransformMakeRotation实现以初始位置为基准,将坐标系统旋转angle弧度(弧度=π/180×角度,M_PI弧度代表180角度)

    // 格式       angle为弧度
    CGAffineTransformMakeRotation(CGFloat angle)
    // 使用       
    self.imageView.transform = CGAffineTransformMakeRotation(M_PI);
    

    2、CGAffineTransformRotate在已有的transform基础上,增加 旋转 效果

    // 格式  
    CGAffineTransformRotate(CGAffineTransform t,
      CGFloat angle)
    // 使用       
    self.imageView.transform = CGAffineTransformRotate(self.imageView.transform,
      M_PI/2.0);
    

    • 最初transform
      控件的transform属性默认值为CGAffineTransformIdentity,可以在形变之后设置该值以还原到最初状态
    // 使用
    self.imageView.transform = CGAffineTransformIdentity;
    

    • 反转变换效果
      CGAffineTransformInvert可以实现于transform相反的效果,比如放大3倍效果则缩小为1/3,向x轴正方向平移100px效果则为向负方向平移100px
    CGAffineTransform transform = CGAffineTransformMakeScale(3, 3);  
    //相反  缩小至1/3                
    transform = CGAffineTransformInvert(transform);
    self.imageView.transform = transform;
    

    • 结合变换效果
      CGAffineTransformConcat结合两种变换
    //定义两种ransform
    CGAffineTransform transform_A = CGAffineTransformMakeTranslation(0, 200);
    CGAffineTransform transform_B = CGAffineTransformMakeScale(0.2, 0.2);
    transform = CGAffineTransformConcat(transform_B, transform_A);
    

    • 判断变换

    1、CGAffineTransformIsIdentity可以判断view.transform当前状态是否是最初状态

    bool CGAffineTransformIsIdentity(CGAffineTransform t)
    

    2、CGAffineTransformEqualToTransform可以判断两种transform是否是一样的

    bool CGAffineTransformEqualToTransform(CGAffineTransform t1, CGAffineTransform t2) 
    

    • 使用仿射变换转换point,size,rect

    1、CGPointApplyAffineTransform转换point,使用一种transform来得到转换后的point

    // transform 可以是移动、放大、旋转
    CGPoint CGPointApplyAffineTransform(CGPoint point,
      CGAffineTransform t)
    // 使用
    CGPoint point =  CGPointMake(123, 222);
    CGPoint pointNew =  CGPointApplyAffineTransform(point, CGAffineTransformMakeTranslation(77, 28));
    
    

    2、CGSizeApplyAffineTransform转换size,使用一种transform来得到转换后的size

    //
    CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t)
    // 使用
    CGSize size = CGSizeMake(33, 44);
    CGSize sizeNew = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(2, 2));
    

    3、CGRectApplyAffineTransform转换rect,使用一种transform来得到转换后的rect

    //
    CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t)
    // 使用
    CGRect rect = CGRectMake(20, 30, 50, 100);
    CGRect rectNew = CGRectApplyAffineTransform(rect, CGAffineTransformMakeRotation(M_PI));
    

    三、CGAffineTransform原理

    CGAffineTransform形变是通过"仿射变换矩阵"来控制的,其中平移是矩阵相加,旋转与缩放则是矩阵相乘,CGAffineTransform形变就是把二维形变使用一个三维矩阵来表示,系统提供了CGAffineTransformMake结构体来控制形变。

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

    该三维变换矩阵如下:
    <center>


    变换矩阵

    变换矩阵

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


    计算

    矩阵相乘
    <center>


    这里写图片描述
    计算结果

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

    所以以下写法都是等同的

    • 移动:[ 1 0 0 1 tx ty ]
    CGAffineTransformMakeTranslation(100, 100);
    CGAffineTransformMake(1, 0, 0, 1, 100, 100);
    
    • 缩放:[ sx 0 0 sy 0 0 ]
    CGAffineTransformMakeScale(2, 0.5);
    CGAffineTransformMake(2, 0, 0, 0.5, 0, 0);
    
    • 旋转:[ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ]
    CGAffineTransformMakeRotation(M_PI*0.5);
    CGAffineTransformMake(cos(M_PI * 0.5), sin(M_PI * 0.5), -sin(M_PI * 0.5), cos(M_PI * 0.5), 0, 0);
    
    • 最初:[ 1 0 0 1 0 0 ]
    CGAffineTransformIdentity;
    CGAffineTransformMake(1, 0, 0, 1, 0, 0);
    

    四、应用

    • 结合UIView动画使用
    [UIView animateWithDuration:1.0 animations:^{
        //缩放
        CGAffineTransform transform = CGAffineTransformMakeScale(2, 2);           
        ws.imageView.transform = transform;
    } completion:^(BOOL finished) {
        [UIView animateWithDuration:1.0 animations:^{
            //回到最初
            ws.imageView.transform =  CGAffineTransformIdentity;              
        } completion:nil]; 
    }];
    
    • 结合手势使用
    //点击手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
    tap.numberOfTapsRequired = 2;
    [self.testView addGestureRecognizer:tap];
    //拖拽手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    [self.testView addGestureRecognizer:pan];
    
    #pragma mark - 点击手势
    -(void)tapAction:(UITapGestureRecognizer *)tap{
        if (CGAffineTransformIsIdentity(self.testView.transform)) {
            [UIView animateWithDuration:0.5 animations:^{
                self.testView.transform = CGAffineTransformScale(self.testView.transform, 1.3, 2);
            }];
        }
        else{
            [UIView animateWithDuration:0.5 animations:^{
                self.testView.transform = CGAffineTransformIdentity;
            }];
        }
    }
    #pragma mark - 拖拽手势
    -(void)panAction:(UIPanGestureRecognizer *)pan{
        //获取手势位置
        CGPoint position = [pan translationInView:self.testView];
        //通过 CGAffineTransformTranslate 获取 新的transform
        self.testView.transform = CGAffineTransformTranslate(self.testView.transform, position.x, position.y);
        //将增加置为 0
        [pan setTranslation:CGPointZero inView:self.testView];
    }
    

    五、Demo地址
    <center>

    UIView动画
    1、UIView动画
    手势
    2、手势
    加载
    3、加载

    六、参考地址

    1、iOS形变之CGAffineTransform

    2、iOS学习必须了解的七大手势

    相关文章

      网友评论

        本文标题:UIView的transform属性使用--CGAffineTr

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