您的位置:首页 > 其它

Core Graphics图形变换

2015-06-06 17:18 344 查看

简单的坐标变换:

Quarzd 2D提供了三个API进行坐标变换:

//1.位移变换
CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty);


对于变换后的坐标系而言,原点位于原坐标系的(tx,ty)处。也相当于在原有坐标系下,所有点的横纵坐标分别增加tx和ty。

//2.旋转变换
CGContextRotateCTM(CGContextRef c, CGFloat angle);


假设点A1经过坐标变换变到了A2,记坐标原点为O。则A1O = A2O(A2在以O为圆心,A1O长度为半径的圆上)且∠A1OA2 = angel。这里的旋转是顺时针旋转。如果想用逆时针旋转的话,使用-angel即可。

//3.缩放变换
CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy);


新坐标系下所有点的横纵坐标等于原横纵坐标分别乘以缩放因子sx和sy。

需要注意的是:这里的变换函数都是作用于上下文(context)的。但和前文所说修改绘图设置不同的是,这些API修改了坐标系统的状态,即使调用CGContextDrawPath方法也无法恢复设置。

坐标系统状态的保存与恢复

我们可以调用这一对方法来进行系统状态的保存和恢复。

CGContextSaveGState(CGContextRef c);//保存当前绘图状态。
CGContextRestoreGState(CGContextRef c);//恢复系统绘图状态。


一个绘图上下文维护了一个绘图系统状态的栈。上下文被初始化时,这个栈为空,所以先调用CGContextSaveGState方法,将当前系统状态入栈,需要恢复时再调用CGContextRestoreGState出栈即可。这里的“状态”(State)不仅包含了当前坐标系统的状态,也包含了设置的填充风格、线条风格、阴影风格等各种状态。需要切记的是,如果还没有保存状态就调用了坐标变换的API,那么就再也无法恢复了。如果此时试图调用CGContextRestoreGState方法,将会对一个空栈执行出栈方法,从而引起报错。

*使用矩阵进行变换

Quartz 2D除了以上三个变换方法之外,还提供了更为一般的,利用矩阵处理坐标变换的方法。

CGContextConcatCTM(CGContextRef c, CGAffineTransform transform);
//Transform 是一个变换矩阵
- (CGAffineTransform)CGContextGetCTM(CGContextRef c);
//获取当前上下文坐标系的变换矩阵


变换矩阵CGAffineTransform transform可以这样创建:

CGAffineTransform transform1 = CGAffineTransformMakeRotation(CGFloat angle);
CGAffineTransform transform2 = CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);
CGAffineTransform transform3 = CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty);


这三个方法分别对应了旋转变换、缩放变换和平移变换的API,因此就不做解释了。

还可以创建一个更一般的变换矩阵:

CGAffineTransform transform = CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);


根据矩阵的运算规则和平移变换的变换规律,点A(x,y)经过transform矩阵作用后的点A’左边应为(ax+cy+tx,bx+dy+ty)。

根据高中数学知识,得出常见的几个变换矩阵:

CGAffineTransformMake(-1, 0, 0, 1, 0, 0);//关于X轴对称变换
CGAffineTransformMake(1, 0, 0, -1, 0, 0);//关于Y轴对称变换
CGAffineTransformMake(0, 1, 1, 0, 0, 0);//关于Y=X对称变换
CGAffineTransformMake(0, -1, -1, 0, 0, 0);//关于X轴对称变换
CGAffineTransformMake(1, 0, tan(α), 1, 0, 0);//水平倾斜α°角
CGAffineTransformMake(1, -tan(α), 0, 1, 0, 0);//竖直倾斜α°角


还可以对已有的矩阵进行修改

CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);//追加平移变换效果,上两个方法类似
CGAffineTransformInvert(CGAffineTransform t);//获取一个变换矩阵的逆矩阵
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);//拼接两个变换矩阵,相当于t1左乘t2


变换矩阵不仅可以作用于上下文的坐标系,还可以作用于CGPoint、CGSize、CGRect等。不仅如此,UIView自身有一个transform属性,支持设置变换矩阵,从而可以对UI控件本身进行坐标变换。

CGPoint newPoint = CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t);
CGSize newSize = CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);
CGRect newRect = CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: