CoreGraphics QuartzCore CGContextTranslateCTM 用法
来源:互联网 发布:恐怖游轮 知乎 编辑:程序博客网 时间:2024/05/22 06:19
Quartz转换实现的原理:Quartz把绘图分成两个部分,
用户空间,即和设备无关,
设备空间,
用户空间和设备空间中间存在一个转换矩阵 : CTM
本章实质是讲解CTM
Quartz提供的3大功能
移动,旋转,缩放
演示如下,首先加载一张图片
void CGContextDrawImage (
CGContextRef c,
CGRect rect,
CGImageRef image
);
移动函数
CGContextTranslateCTM (myContext, 100, 50);
旋转函数
include
static inline double radians (double degrees) {return degrees * M_PI/180;}
CGContextRotateCTM (myContext, radians(–45.));
缩放
CGContextScaleCTM (myContext, .5, .75);
翻转, 两种转换合成后的效果,先把图片移动到右上角,然后旋转180度
CGContextTranslateCTM (myContext, w,h);
CGContextRotateCTM (myContext, radians(-180.));
Quartz 2D编程指南(5)
我们可以通过操作CTM(current transformation matrix)来修改默认的用户空间。在创建图形上下文后,CTM是单位矩阵,我们可以使用 Quartz的变换函数来修改CTM,从而修改用户空间中的绘制操作。
本章内容包括:
- 变换操作函数概览
- 如何修改CTM
- 如何创建一个仿射变换
- 如何选择两个相同的变换
- 如何获取user-to-device-space变换
我们可能使用Quartz内置的变换函数方便的平移、旋转和缩放我们的绘图。只需要短短几行代码,我们便可以按顺序应用变换或结合使用变换。图5-1显示了缩放和旋转一幅图片的效果。我们使用的每个变换操作都更新了CTM。CTM总是用于表示用户空间和设备空间的当前映射关系。这种映射确保了应用程序的输出在任何显示器或打印机上看上去都很棒。
Quartz 2D API提供了5个函数,以允许我们获取和修改CTM。我们可以旋转、平移、缩放CTM。我们还可以联结一个仿射变换矩阵。
有时我们可以不想操作用户空间,直到我们决定将变换应用到CTM时,Quartz为此允许我们创建应用于此的仿射矩阵。我们可以使用另外一组函数来创建仿射变换,这些变换可以与CTM联结在一起。
我们可以不需要了解矩阵的数学含义而使用这些函数。
修改CTM
我们在绘制图像前操作CTM来旋转、缩放或平移page,从而变换我们将要绘制的对象。以变换CTM之前,我们需要保存图形状态,以便绘制后能恢复。我们同样能用仿射矩阵来联结CTM。在本节中,我们将介绍与CTM函数相关的四种操作--平移、旋转、缩放和联结。
假设我们提供了一个可用的图形上下文、一个指向可绘制图像的矩形的指针和一个可用的CGImage对象,则下面一行代码绘制了一个图像。该行代码可以绘制如图5-2所示的图片。在阅读了本节余下的部分后,我们将看到如何将变换应用于图像。
复制代码
- CGContextDrawImage (myContext, rect, myImage);
平移变换根据我们指定的x, y轴的值移动坐标系统的原点。我们通过调用CGContextTranslateCTM函数来修改每个点的x, y坐标值。如图5-3显示了一幅图片沿x轴移动了100个单位,沿y轴移动了50个单位。具体代码如下:
复制代码
- CGContextTranslateCTM (myContext, 100, 50);
旋转变换根据指定的角度来移动坐标空间。我们调用CGContextRotateCTM函数来指定旋转角度(以弧度为单位)。图5-4显示了图片以原点(左下角)为中心旋转45度,代码所下所示:
复制代码
- CGContextRotateCTM (myContext, radians(–45.));
由于旋转操作使图片的部分区域置于上下文之外,所以区域外的部分被裁减。我们用弧度来指定旋转角度。如果需要进行旋转操作,下面的代码将会很有用
复制代码
- #include
- static inline double radians (double degrees) {return degrees * M_PI/180;}
复制代码
- CGContextScaleCTM (myContext, .5, .75);
联合变换将两个矩阵相乘来联接现价变换操作。我们可以联接多个矩阵来得到一个包含所有矩阵累积效果矩阵。通过调用CGContextConcatCTM来联接CTM和仿射矩阵。
另外一种得到累积效果的方式是执行两个或多个变换操作而不恢复图形状态。图5-6显示了先平移后旋转一幅图片的效果,代码如下:
复制代码
- CGContextTranslateCTM (myContext, w,h);
- CGContextRotateCTM (myContext, radians(-180.));
图5-7显示了平移、缩放和旋转一幅图片,代码如下:
复制代码
- CGContextTranslateCTM (myContext, w/4, 0);
- CGContextScaleCTM (myContext, .25, .5);
- CGContextRotateCTM (myContext, radians ( 22.));
变换操作的顺序会影响到最终的效果。如果调换顺序,将得到不同的结果。调换上面代码的顺序将得到如图5-8所示的效果,代码如下:
复制代码
- CGContextRotateCTM (myContext, radians ( 22.));
- CGContextScaleCTM (myContext, .25, .5);
- CGContextTranslateCTM (myContext, w/4, 0);
创建仿射变换
仿射变换操作在矩阵上,而不是在CTM上。我们可以使用这些函数来构造一个之后用于CTM(调用函数CGContextConcatCTM)的矩阵。仿射变换函数使用或者返回一个CGAffineTransform数据对象。我们可以构建简单或复杂的仿射变换。
仿射变换函数能实现与CTM函数相同的操作--平移、旋转、缩放、联合。表5-1列出了仿射变换函数及其用途。注意每种变换都有两个函数。
表5-1 仿射变换函数
函数
用途
CGAffineTransformMakeTra
CGAffineTransformTransla
CGAffineTransformMakeRot
CGAffineTransformRotate
在已存在的矩阵中使用旋转
CGAffineTransformMakeSca
CGAffineTransformScale
在已存在的矩阵中使用缩放Quartz同样提供了一个仿射变换函数(CGAffineTransformInvert)来倒置矩阵。倒置操作通常用于在变换对象中提供点的倒置变换。当我们需要恢复一个被矩阵变换的值时,可以使用倒置操作。将值与倒置矩阵相乘,就可得到原先的值。我们通常不需要倒置操作,因为我们可以通过保存和恢复图形状态来倒置CTM的效果。
在一些情况下,我们可能不需要变换整修空间,而只是一个点或一个大小。我们通过调用CGPointApplyAffineTransf
可以通过调用函数CGAffineTransformMake来创建一个新的仿射变换,但与其它函数不同的是,它需要提供一个矩阵实体。
评价仿射变换
我们可以通过调用CGAffineTransformEqualTo
函数CGAffineTransformIsIdent
获取用户空间到设备空间的变换
当使用Quartz 2D时,我们只是在用户空间下工作。Quartz为我们处理用户空间和设备空间的转换。如果我们的应用程序需要获取Quartz转换用户空间和设备空间的仿射变换,我们可以调用函数CGContextGetUserSpaceToD
Quartz提供了一系列的函数来转换用户空间和设备空间的几何体。我们会发现这些函数使用赶来比使用CGContextGetUserSpaceToD
- 点:函数CGContextConvertPointToD
eviceSpace和CGContextConvertPointToU serSpace将一个CGPoint数据结构从一个空间变换到另一个空间。 - 大小:函数CGContextConvertSizeToDe
viceSpace和CGContextConvertSizeToUs erSpace将一个CGSize数据结构从一个空间变换到另一个空间。 - 矩形:函数CGContextConvertRectToDe
viceSpace和CGContextConvertRectToUs erSpace将一个CGPoint数据结构从一个空间变换到另一个空间。
首先要说的是CALayers 是屏幕上的一个具有可见内容的矩形区域,每个UIView都有一个根CALayer,其所有的绘制(视觉效果)都是在这个layer上进行的。(译者注:为验证这点,我写下了如下代码:
2
3
4
5
6
7
8
9
10
lable.text = @"test";
[self.view addSubview: lable];
lable.backgroundColor = [UIColor clearColor];
[lable release];
// 设定CALayer
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius =20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
请注意,我创建的UILable始终随着UIView的根CALayer的缩放而改变位置。)
其次,CALayer的可以影响其外观的特性有:
- 层的大小尺寸
- 背景色
- 内容(比如图像或是使用Core Graphics绘制的内容)
- 是否使用圆角
- 是否使用阴影
- 等等
需要说明的是CALayer的大部分属性都可以用来实现动画效果。
另外,你可以直接使用CALayer,也可以使用其子类,如CAGradientLayer,CATextLayer, CAShapeLayer等等。
示例
首先在Xcode中创建一个View-based App,CALayer是属于QuartzCore framework的,所以需要引入QuartzCore framework,另外在程序中包括QuartzCore.h。
第一个例子是创建一个带圆角的层,在你的ViewController中的ViewDidLoad中加入下面代码:
2
3
4
5
6
7
#import
// Uncomment viewDidLoad and add the following lines
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius =20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
然后添加一个带阴影效果的子层,加入下列代码:
2
3
4
5
6
7
8
sublayer.backgroundColor = [UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
[self.view.layer addSublayer:sublayer];
为子层增加内容(图片),你还可以设置层的边框,代码如下:
2
3
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth =2.0;
如果你希望子层也是圆角怎么办?你可能说很容易设置cornerRadius属性就行。实际上你即算是设置了cornerRadius属性,图片仍然不会显示圆角。你还需要设置masksToBounds为YES。但是这样做还是不够的,因为如果是这样,这个层的阴影显示就没有了。简单的实现方法如下(通过两个层来实现):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sublayer.backgroundColor =[UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius =5.0;
sublayer.shadowColor =[UIColor blackColor].CGColor;
sublayer.shadowOpacity =0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth =2.0;
sublayer.cornerRadius =10.0;
[self.view.layer addSublayer:sublayer];
CALayer *imageLayer =[CALayer layer];
imageLayer.frame = sublayer.bounds;
imageLayer.cornerRadius =10.0;
imageLayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage;
imageLayer.masksToBounds =YES;
[sublayer addSublayer:imageLayer];
最后,还介绍一下自绘图型的实现,其要点是要设置所绘制层的delegate。比如在我们的例子中使用ViewController作为delegate,那么就需要在ViewController中实现drawLayer:inContext方法,对层进行绘制工作。另外,还需要调用setNeedsDisplay,来通知层需要进行绘制了,于是层才会通过对delegate的drawLayer:inContext方法进行调用。
代码如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
CGColorRef dotColor =[UIColor colorWithHue:0 saturation:0 brightness:0.07 alpha:1.0].CGColor;
CGColorRef shadowColor =[UIColor colorWithRed:1 green:1 blue:1 alpha:0.1].CGColor;
CGContextSetFillColorWit
CGContextSetShadowWithCo
CGContextAddArc(context, 3, 3, 4, 0, radians(360), 0);
CGContextFillPath(context);
CGContextAddArc(context, 16, 16, 4, 0, radians(360), 0);
CGContextFillPath(context);
}
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
CGColorRef bgColor =[UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
CGContextSetFillColorWit
CGContextFillRect(context, layer.bounds);
staticconst CGPatternCallbacks callbacks ={0, &MyDrawColoredPattern, NULL};
CGContextSaveGState(context);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePatter
CGContextSetFillColorSpa
CGColorSpaceRelease(patternSpace);
CGPatternRef pattern = CGPatternCreate(NULL,
layer.bounds,
CGAffineTransformIdentit
24,
24,
kCGPatternTilingConstant
true,
&callbacks);
CGFloat alpha =1.0;
CGContextSetFillPattern(context, pattern, &alpha);
CGPatternRelease(pattern);
CGContextFillRect(context, layer.bounds);
CGContextRestoreGState(context);
}
还需要注意,radians是一个自定义函数:
- CoreGraphics QuartzCore CGContextTranslateCTM 用法
- CoreGraphics QuartzCore CGContextTranslateCTM 用法
- CoreGraphics QuartzCore CGContextTranslateCTM 用法
- CoreGraphics.h和QuartzCore
- CoreGraphics,QuartzCore, CoreAnimation
- 对CoreGraphics和QuartzCore的理解
- CGContextTranslateCTM
- CGContextTranslateCTM
- QuartzCore
- QuartzCore
- QuartzCore
- QuartzCore
- CALayer的transform属性(QuartzCore框架)和view的transform属性(CoreGraphics框架)
- CoreGraphics
- CoreGraphics
- CoreGraphics
- CoreGraphics
- CGContextScaleCTM,CGContextTranslateCTM
- LVS+keeplived+nginx+apache搭建高可用、高性能php集群
- Android adb 唤醒屏幕 点亮屏幕
- [Bzoj3524][Poi2014]Couriers
- 内核调试神器SystemTap — 简介与使用(一)
- 微软下一代云环境Web开发框架ASP.NET vNext预览
- CoreGraphics QuartzCore CGContextTranslateCTM 用法
- 随记:我们需要怎样的数学教育?
- 第十二周(项目一)——长颈鹿类对动物类的继承 。
- Access restriction: The type JPEGCodec is not accessible due to restriction on required library
- 程序员技术练级攻略
- C# 之泛型详解
- 0803-APP-Preference-dependency
- 室内装修的基本项目与流程
- FzrOJ 1019 电路实验