CGAffineTransform 放射变换

CGAffineTransform 的结构如下

struct CGAffineTransform {

CGFloat a;

CGFloat b;

CGFloat c;

CGFloat d;

CGFloat tx;

CGFloat ty;

};

typedef struct CGAffineTransform CGAffineTransform;

它其实表示的是一个矩阵

 

懂OpenGL的人,一看就明白了哈

因为最后一列总是是(0,0,1),所以有用的信息就是前面两列

对一个view进行仿射变化就相当于对view上的每个点做一个乘法

结果就是

基本上就是如果不看c和b的话

a表示x水平方向的缩放,tx表示x水平方向的偏移

d表示y垂直方向的缩放,ty表示y垂直方向的偏移

如果b和c不为零的话,那么视图肯定发生了旋转

常量

CGAffineTransformIdentity
const CGAffineTransformCGAffineTransformIdentity;

表示单位矩阵

创建一个仿射矩阵

  • CGAffineTransformMake 直接赋值来创建
  • CGAffineTransformMakeRotation 设置角度来生成矩阵
  • 结果就是
  • CGAffineTransformMakeScale  设置缩放,及改变a、d的值
  • CGAffineTransformMakeTranslation  设置偏移

改变已经存在的放射矩阵

  • CGAffineTransformTranslate  原始的基础上加上偏移
  • CGAffineTransformScale加上缩放
  • CGAffineTransformRotate加上旋转
  • CGAffineTransformInvert 反向的仿射矩阵比如(x,y)通过矩阵t得到了(x',y')那么通过这个函数生成的t'作用与(x',y')就能得到原始的(x,y)
  • CGAffineTransformConcat 通过两个已经存在的放射矩阵生成一个新的矩阵t' = t1 * t2

应用仿射矩阵

  • CGPointApplyAffineTransform 得到新的点
  • CGSizeApplyAffineTransform  得到新的size
  • CGRectApplyAffineTransform  得到新的rect

评测矩阵

  • CGAffineTransformIsIdentity  是否是CGAffineTransformIsIdentity
  • CGAffineTransformEqualToTransform 看两个矩阵是否相等

还原transform
缩放
水平方向缩放 

  sqrt(a^2+c^2)

垂直方向缩放 

  sqrt(b^2+d^2)

旋转的角度 

 

  tan(angle) = b / a

偏移 tx, ty  

CGAffineTransform makeTransform(CGFloat xScale, CGFloat yScale, 
CGFloat theta, CGFloat tx, CGFloat ty){
    CGAffineTransform transform = CGAffineTransformIdentity;

    transform.a = xScale * cos(theta);
    transform.b = yScale * sin(theta);
    transform.c = xScale * -sin(theta);
    transform.d = yScale * cos(theta);
    transform.tx = tx;
    transform.ty = ty;

    return transform;
}

应用

放射矩阵一个常用的情形就是根据用户的手势来相应的改变视图的变换

UIPanGestureRecognizer  对应位移

UIPinchGestureRecognizer  对应缩放

UIRotationGestureRecognizer 对应旋转

通常如果需要看到实时的手指移动视图就相应的变换的技巧就是,每次接收到对应的gesture时间就相应的改变view的transform,然后吧这个gesture对应的translationscale、rotation置为初始值。

参考 http://www.cnblogs.com/v2m_/archive/2013/05/09/3070187.html

平移变换将路径或图形上下文中的形状的当前位置平移到另一个相对位置。举例来说,如果你在(10,20)的位置处画一个点,对它应用(30,40)的平移变换,然后绘制它,这个点将被绘制在(40,60)的位置处。为了创建一个平移变换,使用CGAffineTransformMakeTranslation函数,它将返回一个CGAffineTransform类型的仿射变换,这个函数的两个参数指定x和y方向上以点为单位的平移量。我们还可以使用CGContextTranslateCTM过程对图形上下文应用变换。

 平移变换路径

 

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
    
    CGAffineTransform transform = CGAffineTransformMakeTranslation(100.0f, 0.0f);


    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGPathAddRect(path, &transform, rectangle);
    CGContextAddPath(currentContext, path);
    [[UIColor brownColor] setStroke];
    [[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    CGPathRelease(path);
}

平移变换图形上下文

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 300.0f);
    CGPathAddRect(path, NULL, rectangle);
    
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);
    
    CGContextTranslateCTM(currentContext, 100.0f, 40.0f);

    CGContextAddPath(currentContext, path);
    [[UIColor colorWithRed:0.20f green:0.6f blue:0.8f alpha:1.0f] setFill];
    [[UIColor brownColor] setStroke];
    
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    
    CGPathRelease(path);
    
    CGContextRestoreGState(currentContext);   
}

缩放是另外一个你可以使用的变换。你可以很容易地让CoreGraphics 对形状进行缩放,例如一个圆形缩放到原来的100倍。要创建一个仿射缩放变换,使用CGAffineTransformMakeScale函数,它返回一个CGAffineTransform 类型的变换对象。如果你想直接对一个图形上下文使用缩放变换,使用CGContextScaleCTM过程来缩放当前变换矩阵。

缩放路径

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
    

    CGAffineTransform transform = CGAffineTransformMakeScale(0.5f, 0.5f);

    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGPathAddRect(path, &transform, rectangle);
    CGContextAddPath(currentContext, path);
    [[UIColor brownColor] setStroke];
    [[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    CGPathRelease(path);
}

 缩放图形上下文

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 300.0f);
    CGPathAddRect(path, NULL, rectangle);
    
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);
    

    CGContextScaleCTM(currentContext, 0.5f, 0.5f);

    CGContextAddPath(currentContext, path);
    [[UIColor colorWithRed:0.20f green:0.6f blue:0.8f alpha:1.0f] setFill];
    [[UIColor brownColor] setStroke];
    
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    
    CGPathRelease(path);
    
    CGContextRestoreGState(currentContext);   
}

就像缩放和平移,你可以对绘制在路径上的形状和图形上下文应用旋转变换。你可以使用CGAffineTransformMakeRoation函数和一个旋转的弧度值来获取一个CGAffineTransform类型的变换.如果你想对整个图形上下文旋转指定角度,可以使用CGContextRotateCTM过程。

旋转路径

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
    
    CGAffineTransform transform = CGAffineTransformMakeRotation((45.0f * M_PI) / 180.0f);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGPathAddRect(path, &transform, rectangle);
    CGContextAddPath(currentContext, path);
    [[UIColor brownColor] setStroke];
    [[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    CGPathRelease(path);
}

 旋转图形上下文

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 300.0f);
    CGPathAddRect(path, NULL, rectangle);
    
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);
    CGContextRotateCTM(currentContext, (45.0f * M_PI) / 180.0f);
    CGContextAddPath(currentContext, path);
    [[UIColor colorWithRed:0.20f green:0.6f blue:0.8f alpha:1.0f] setFill];
    [[UIColor brownColor] setStroke];
    
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    
    CGPathRelease(path);
    
    CGContextRestoreGState(currentContext);   
}

另外我们还可以组合变换效果,使用 CGAffineTransformConcact函数组合两个变换效果,这个函数的两个参数都是类型为CGAffineTransform类型的变换。

组合多个变换效果,同时进行平移和缩放

-(void)drawRect:(CGRect)rect
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect rectangle = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
    
    CGAffineTransform transform1 = CGAffineTransformMakeTranslation(100.0f, 0.0f);
    CGAffineTransform transform2 = CGAffineTransformMakeScale(0.5f, 0.5f);
    CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGPathAddRect(path, &transform, rectangle);
    CGContextAddPath(currentContext, path);
    [[UIColor brownColor] setStroke];
    [[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
    CGContextSetLineWidth(currentContext, 5.0f);
    CGContextDrawPath(currentContext, kCGPathFillStroke);
    CGPathRelease(path);
}

参考:http://my.oschina.net/CarlHuang/blog/138801

 

  

posted @ 2013-09-21 20:57  jiangmingz  阅读(416)  评论(0编辑  收藏  举报