Quartz 2D还可以将图像绘制到图形上下文。 (void)drawImage:(CGContextRef)context{ UIImage *image[UIImage imageNamed:image2.jpg]; //从某一点开始绘制 [image drawAtPoint:CGPointMake(10, 50)]; //绘制到指定的矩形中注意如果大小不合适会会进行拉伸 // [image drawInRect:CGRectMake(10, 50, 300, 450)]; //平铺绘制 // [image drawAsPatternInRect:CGRectMake(0, 0, 320, 568)]; }运行效果绘制渐变填充从前面的示例中我们可以看到如何设置填充颜色事实上很多时候纯色的填充并不能满足我们的需求例如有时候我们要绘制一些图形可能需要设置一个漂亮的背景这个时候我们可能就会选择渐变填充方式。Quartz 2D的渐变方式分为两种a.线性渐变线渐变色以直线方式从开始位置逐渐向结束位置渐变b.径向渐变以中心点为圆心从起始渐变色向四周辐射直到终止渐变色要做渐变则必须先设置从开始位置到结束位置的渐变颜色做过photoshop的朋友相信对于渐变色设置并不陌生只要在指定位置指定不同的颜色剩下的事情交给系统处理即可如下图在起始位置、3/10位置、结束位置指定了三种颜色就形成由三种颜色组成的渐变色另外在iOS中绘制渐变还需要注意一点就是指定颜色空间所谓颜色空间就是不同颜色在不同的维度上取值最终组成一种颜色的过程。就拿RGB来说如果将红色、绿色、蓝色看成是x、y、z轴坐标系那么在三个坐标上分别取0~255范围内的不同值则可以组成各类颜色。当然不同颜色空间的“坐标系”也是不同的也就是说颜色表示的方式是不同的常用的颜色空间除了RGB还有CMYK印刷业常用这种颜色模式、Gray。在使用Quartz 2D绘图时我们的颜色除了使用常规的方法如何前面CGContextSetRGBFillColor(CGContextRef context, CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)方法设置RGB和透明度外有时还会遇到颜色参数是一个数组情况。如使用颜色空间填充时用到的CGContextSetFillColor(CGContextRef context, const CGFloat *components)方法这个时候components数组中具体是如何存储颜色就要根据颜色空间而定如果颜色空间使用RGB则数组中的元素四个为一组分别是red红、green绿、blue蓝、alpha透明度如果使用CMYK颜色空间那么数组中的元素五个为一组分别是cyan青、magenta洋红、yellow黄、black黑、alpha透明度。下面的代码分别演示了两种渐变方式具体渐变绘制函数参数代码中已经注释的很清楚了// // KCView3.m // Quartz2D // // Created by Kenshin Cui on 14-3-16. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import KCView3.h implementation KCView3 -(void)drawRect:(CGRect)rect{ CGContextRef contextUIGraphicsGetCurrentContext(); // [self drawLinearGradient:context]; [self drawRadialGradient:context]; } #pragma mark 线性渐变 -(void)drawLinearGradient:(CGContextRef)context{ //使用rgb颜色空间 CGColorSpaceRef colorSpaceCGColorSpaceCreateDeviceRGB(); /*指定渐变色 space:颜色空间 components:颜色数组,注意由于指定了RGB颜色空间那么四个数组元素表示一个颜色red、green、blue、alpha 如果有三个颜色则这个数组有4*3个元素 locations:颜色所在位置范围0~1这个数组的个数不小于components中存放颜色的个数 count:渐变个数等于locations的个数 */ CGFloat compoents[12]{ 248.0/255.0,86.0/255.0,86.0/255.0,1, 249.0/255.0,127.0/255.0,127.0/255.0,1, 1.0,1.0,1.0,1.0 }; CGFloat locations[3]{0,0.3,1.0}; CGGradientRef gradient CGGradientCreateWithColorComponents(colorSpace, compoents, locations, 3); /*绘制线性渐变 context:图形上下文 gradient:渐变色 startPoint:起始位置 endPoint:终止位置 options:绘制方式,kCGGradientDrawsBeforeStartLocation 开始位置之前就进行绘制到结束位置之后不再绘制 kCGGradientDrawsAfterEndLocation开始位置之前不进行绘制到结束点之后继续填充 */ CGContextDrawLinearGradient(context, gradient, CGPointZero, CGPointMake(320, 300), kCGGradientDrawsAfterEndLocation); //释放颜色空间 CGColorSpaceRelease(colorSpace); } #pragma mark 径向渐变 -(void)drawRadialGradient:(CGContextRef)context{ //使用rgb颜色空间 CGColorSpaceRef colorSpaceCGColorSpaceCreateDeviceRGB(); /*指定渐变色 space:颜色空间 components:颜色数组,注意由于指定了RGB颜色空间那么四个数组元素表示一个颜色red、green、blue、alpha 如果有三个颜色则这个数组有4*3个元素 locations:颜色所在位置范围0~1这个数组的个数不小于components中存放颜色的个数 count:渐变个数等于locations的个数 */ CGFloat compoents[12]{ 248.0/255.0,86.0/255.0,86.0/255.0,1, 249.0/255.0,127.0/255.0,127.0/255.0,1, 1.0,1.0,1.0,1.0 }; CGFloat locations[3]{0,0.3,1.0}; CGGradientRef gradient CGGradientCreateWithColorComponents(colorSpace, compoents, locations, 3); /*绘制径向渐变 context:图形上下文 gradient:渐变色 startCenter:起始点位置 startRadius:起始半径通常为0否则在此半径范围内容无任何填充 endCenter:终点位置通常和起始点相同否则会有偏移 endRadius:终点半径也就是渐变的扩散长度 options:绘制方式,kCGGradientDrawsBeforeStartLocation 开始位置之前就进行绘制但是到结束位置之后不再绘制 kCGGradientDrawsAfterEndLocation开始位置之前不进行绘制但到结束点之后继续填充 */ CGContextDrawRadialGradient(context, gradient, CGPointMake(160, 284),0, CGPointMake(165, 289), 150, kCGGradientDrawsAfterEndLocation); //释放颜色空间 CGColorSpaceRelease(colorSpace); } end运行效果扩展--渐变填充上面我们只是绘制渐变到图形上下文实际开发中有时候我们还需要填充对应的渐变色例如现在绘制了一个矩形如何填充成渐变色呢在此可以利用渐变裁切来完成当然利用层CALayer更加方便但这不在今天的话题讨论范围内特别说明一下区域裁切并不仅仅适用于渐变填充对于其他图形绘制仍然适用并且注意裁切只能限于矩形裁切。-(void)drawRectWithLinearGradientFill:(CGContextRef)context{ CGColorSpaceRef colorSpaceCGColorSpaceCreateDeviceRGB(); //裁切处一块矩形用于显示注意必须先裁切再调用渐变 //CGContextClipToRect(context, CGRectMake(20, 50, 280, 300)); //裁切还可以使用UIKit中对应的方法 UIRectClip(CGRectMake(20, 50, 280, 300)); CGFloat compoents[12]{ 248.0/255.0,86.0/255.0,86.0/255.0,1, 249.0/255.0,127.0/255.0,127.0/255.0,1, 1.0,1.0,1.0,1.0 }; CGFloat locations[3]{0,0.3,1.0}; CGGradientRef gradient CGGradientCreateWithColorComponents(colorSpace, compoents, locations, 3); CGContextDrawLinearGradient(context, gradient, CGPointMake(20, 50), CGPointMake(300, 300), kCGGradientDrawsAfterEndLocation); //释放颜色空间 CGColorSpaceRelease(colorSpace); }运行效果其他状态设置常用的图形上下文状态设置上面基本都用到了我们不再一一解释这里着重说一下叠加模式和填充模式初学者对于这两个状态设置往往容易产生疑惑。叠加模式使用Quartz 2D绘图时后面绘制的图像会覆盖前面的默认情况下如果前面的被覆盖后将看不到后面的内容但是有时候这个结果并不是我们想要的因此在Quartz 2D中提供了填充模式供开发者配置调整。由于填充模式类别特别多因此下面以一个例子来说明-(void)drawRectByUIKitWithContext2:(CGContextRef)context{ CGRect rect CGRectMake(0, 130.0, 320.0, 50.0); CGRect rect1 CGRectMake(0, 390.0, 320.0, 50.0); CGRect rect2CGRectMake(20, 50.0, 10.0, 250.0); CGRect rect3CGRectMake(40.0, 50.0, 10.0, 250.0); CGRect rect4CGRectMake(60.0, 50.0, 10.0, 250.0); CGRect rect5CGRectMake(80.0, 50.0, 10.0, 250.0); CGRect rect6CGRectMake(100.0, 50.0, 10.0, 250.0); CGRect rect7CGRectMake(120.0, 50.0, 10.0, 250.0); CGRect rect8CGRectMake(140.0, 50.0, 10.0, 250.0); CGRect rect9CGRectMake(160.0, 50.0, 10.0, 250.0); CGRect rect10CGRectMake(180.0, 50.0, 10.0, 250.0); CGRect rect11CGRectMake(200.0, 50.0, 10.0, 250.0); CGRect rect12CGRectMake(220.0, 50.0, 10.0, 250.0); CGRect rect13CGRectMake(240.0, 50.0, 10.0, 250.0); CGRect rect14CGRectMake(260.0, 50.0, 10.0, 250.0); CGRect rect15CGRectMake(280.0, 50.0, 10.0, 250.0); CGRect rect16CGRectMake(30.0, 310.0, 10.0, 250.0); CGRect rect17CGRectMake(50.0, 310.0, 10.0, 250.0); CGRect rect18CGRectMake(70.0, 310.0, 10.0, 250.0); CGRect rect19CGRectMake(90.0, 310.0, 10.0, 250.0); CGRect rect20CGRectMake(110.0, 310.0, 10.0, 250.0); CGRect rect21CGRectMake(130.0, 310.0, 10.0, 250.0); CGRect rect22CGRectMake(150.0, 310.0, 10.0, 250.0); CGRect rect23CGRectMake(170.0, 310.0, 10.0, 250.0); CGRect rect24CGRectMake(190.0, 310.0, 10.0, 250.0); CGRect rect25CGRectMake(210.0, 310.0, 10.0, 250.0); CGRect rect26CGRectMake(230.0, 310.0, 10.0, 250.0); CGRect rect27CGRectMake(250.0, 310.0, 10.0, 250.0); CGRect rect28CGRectMake(270.0, 310.0, 10.0, 250.0); CGRect rect29CGRectMake(290.0, 310.0, 10.0, 250.0); [[UIColor yellowColor]set]; UIRectFill(rect); [[UIColor greenColor]setFill]; UIRectFill(rect1); [[UIColor redColor]setFill]; UIRectFillUsingBlendMode(rect2, kCGBlendModeClear); UIRectFillUsingBlendMode(rect3, kCGBlendModeColor); UIRectFillUsingBlendMode(rect4, kCGBlendModeColorBurn); UIRectFillUsingBlendMode(rect5, kCGBlendModeColorDodge); UIRectFillUsingBlendMode(rect6, kCGBlendModeCopy); UIRectFillUsingBlendMode(rect7, kCGBlendModeDarken); UIRectFillUsingBlendMode(rect8, kCGBlendModeDestinationAtop); UIRectFillUsingBlendMode(rect9, kCGBlendModeDestinationIn); UIRectFillUsingBlendMode(rect10, kCGBlendModeDestinationOut); UIRectFillUsingBlendMode(rect11, kCGBlendModeDestinationOver); UIRectFillUsingBlendMode(rect12, kCGBlendModeDifference); UIRectFillUsingBlendMode(rect13, kCGBlendModeExclusion); UIRectFillUsingBlendMode(rect14, kCGBlendModeHardLight); UIRectFillUsingBlendMode(rect15, kCGBlendModeHue); UIRectFillUsingBlendMode(rect16, kCGBlendModeLighten); UIRectFillUsingBlendMode(rect17, kCGBlendModeLuminosity); UIRectFillUsingBlendMode(rect18, kCGBlendModeMultiply); UIRectFillUsingBlendMode(rect19, kCGBlendModeNormal); UIRectFillUsingBlendMode(rect20, kCGBlendModeOverlay); UIRectFillUsingBlendMode(rect21, kCGBlendModePlusDarker); UIRectFillUsingBlendMode(rect22, kCGBlendModePlusLighter); UIRectFillUsingBlendMode(rect23, kCGBlendModeSaturation); UIRectFillUsingBlendMode(rect24, kCGBlendModeScreen); UIRectFillUsingBlendMode(rect25, kCGBlendModeSoftLight); UIRectFillUsingBlendMode(rect26, kCGBlendModeSourceAtop); UIRectFillUsingBlendMode(rect27, kCGBlendModeSourceIn); UIRectFillUsingBlendMode(rect28, kCGBlendModeSourceOut); UIRectFillUsingBlendMode(rect29, kCGBlendModeXOR); }运行效果相信大家对比代码和显示效果并不难发现每种叠加的效果。例子中只是使用UIKit的封装方法进行叠加模式设置更一般的方法当然是使用CGContextSetBlendMode(CGContextRef context, CGBlendMode mode)方法进行设置。填充模式前面的示例中已经演示过纯色填充、渐变填充而有时我们需要按一定的自定义样式进行填充这种方式有点类似于贴瓷砖的方式。我们知道如果家里贴地板或瓷砖时通常我们会先选择一种瓷砖样式根据房间面积我们购买不同量的瓷砖。但是不管买多少这些瓷砖的样式都是一模一样的。填充模式就是为了达到这种效果而产生的我们只需要绘制一个瓷砖的样式然后让程序自动调用这种样式填充指定大小的区域。Quartz 2D支持两种填充模式有颜色填充和无颜色填充。两种模式使用起来区别很小有颜色填充就是在绘制瓷砖时就指定颜色在调用填充时就不用再指定瓷砖颜色无颜色填充模式就是绘制瓷砖时不用指定任何颜色在调用填充时再指定具体填充颜色。相比较无颜色填充模式而言有颜色填充模式更加的灵活推荐使用。下面我们具体看一下如何按指定模式进行图形填充1.在使用填充模式时首先要构建一个符合CGPatternDrawPatternCallback签名的方法这个方法专门用来创建“瓷砖”。注意如果使用有颜色填充模式需要设置填充色。例如我们定义一个方法drawTile绘制以下瓷砖有颜色填充2.接着需要指定一个填充的颜色空间这个颜色空间跟前面绘制渐变的颜色空间不太一样前面创建渐变使用的颜色空间是设备无关的我们需要基于这个颜色空间创建一个颜色空间专门用于填充注意对于有颜色填充创建填充颜色空间参数为NULL不用基于设备无关的颜色空间创建。3.然后我们就可以使用CGPatternCreate方法创建一个填充模式创建填充模式时需要注意其中的参数在代码中已经做了一一解释这里注意对于有颜色填充模式isColored设置为true否则为false。4.最后调用CGContextSetFillPattern方法给图形上下文指定填充模式这个时候注意最后一个参数如果是有颜色填充模式最后一个参数为透明度alpa的地址对于无颜色填充模式最后一个参数是当前填充颜色空间的颜色数组。5.绘制图形这里我们绘制一个矩形。6.释放资源。下面是具体代码包含两种填充模式代码可以一一运行// // UIView4.m // Quartz2D // // Created by Kenshin Cui on 14-3-17. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import KCView.h #define TILE_SIZE 20 implementation KCView -(void)drawRect:(CGRect)rect{ CGContextRef contextUIGraphicsGetCurrentContext(); [self drawBackgroundWithColoredPattern:context]; // [self drawBackgroundWithPattern:context]; } #pragma mark - 有颜色填充模式 void drawColoredTile(void *info,CGContextRef context){ //有颜色填充这里设置填充色 CGContextSetRGBFillColor(context, 254.0/255.0, 52.0/255.0, 90.0/255.0, 1); CGContextFillRect(context, CGRectMake(0, 0, TILE_SIZE, TILE_SIZE)); CGContextFillRect(context, CGRectMake(TILE_SIZE, TILE_SIZE, TILE_SIZE, TILE_SIZE)); } -(void)drawBackgroundWithColoredPattern:(CGContextRef)context{ //设备无关的颜色空间 // CGColorSpaceRef rgbSpace CGColorSpaceCreateDeviceRGB(); //模式填充颜色空间,注意对于有颜色填充模式这里传NULL CGColorSpaceRef colorSpaceCGColorSpaceCreatePattern(NULL); //将填充色颜色空间设置为模式填充的颜色空间 CGContextSetFillColorSpace(context, colorSpace); //填充模式回调函数结构体 CGPatternCallbacks callback{0,drawColoredTile,NULL}; /*填充模式 info://传递给callback的参数 bounds:瓷砖大小 matrix:形变 xStep:瓷砖横向间距 yStep:瓷砖纵向间距 tiling:贴砖的方法 isClored:绘制的瓷砖是否已经指定了颜色(对于有颜色瓷砖此处指定位true) callbacks:回调函数 */ CGPatternRef patternCGPatternCreate(NULL, CGRectMake(0, 0, 2*TILE_SIZE, 2*TILE_SIZE), CGAffineTransformIdentity,2*TILE_SIZE 5,2*TILE_SIZE 5, kCGPatternTilingNoDistortion, true, callback); CGFloat alpha1; //注意最后一个参数对于有颜色瓷砖指定为透明度的参数地址对于无颜色瓷砖则指定当前颜色空间对应的颜色数组 CGContextSetFillPattern(context, pattern, alpha); UIRectFill(CGRectMake(0, 0, 320, 568)); // CGColorSpaceRelease(rgbSpace); CGColorSpaceRelease(colorSpace); CGPatternRelease(pattern); } #pragma mark - 无颜色填充模式 //填充瓷砖的回调函数必须满足CGPatternCallbacks签名 void drawTile(void *info,CGContextRef context){ CGContextFillRect(context, CGRectMake(0, 0, TILE_SIZE, TILE_SIZE)); CGContextFillRect(context, CGRectMake(TILE_SIZE, TILE_SIZE, TILE_SIZE, TILE_SIZE)); } -(void)drawBackgroundWithPattern:(CGContextRef)context{ //设备无关的颜色空间 CGColorSpaceRef rgbSpace CGColorSpaceCreateDeviceRGB(); //模式填充颜色空间 CGColorSpaceRef colorSpaceCGColorSpaceCreatePattern(rgbSpace); //将填充色颜色空间设置为模式填充的颜色空间 CGContextSetFillColorSpace(context, colorSpace); //填充模式回调函数结构体 CGPatternCallbacks callback{0,drawTile,NULL}; /*填充模式 info://传递给callback的参数 bounds:瓷砖大小 matrix:形变 xStep:瓷砖横向间距 yStep:瓷砖纵向间距 tiling:贴砖的方法瓷砖摆放的方式 isClored:绘制的瓷砖是否已经指定了颜色对于无颜色瓷砖此处指定位false callbacks:回调函数 */ CGPatternRef patternCGPatternCreate(NULL, CGRectMake(0, 0, 2*TILE_SIZE, 2*TILE_SIZE), CGAffineTransformIdentity,2*TILE_SIZE 5,2*TILE_SIZE 5, kCGPatternTilingNoDistortion, false, callback); CGFloat components[]{254.0/255.0,52.0/255.0,90.0/255.0,1.0}; //注意最后一个参数对于无颜色填充模式指定为当前颜色空间颜色数据 CGContextSetFillPattern(context, pattern, components); // CGContextSetStrokePattern(context, pattern, components); UIRectFill(CGRectMake(0, 0, 320, 568)); CGColorSpaceRelease(rgbSpace); CGColorSpaceRelease(colorSpace); CGPatternRelease(pattern); } end运行效果这里强调一点在drawTile回调方法中不要使用UIKit封装方法进行图形绘制例如UIRectFill等由于这个方法由Core Graphics内部调用而Core Graphics考虑到跨平台问题内部是不允许调用UIKit方法的。