标签:
Quartz 2D各种绘制实例
首先说一下,本篇文章只是介绍怎么使用Quartz 2D绘制一些常用的图像效果,关于Quartz和其他相关技术请查看笔者之前写的完整版(Quartz 2D详解)
一:画线
1 // 1.获取跟当前View相关联的layer上下文(画板) 2 // 总结:目前获取的所有上下文都是以UIGraphics开头 3 // CGContextRef:上下文类型 4 // CG:CoreGraphics Ref:引用 5 CGContextRef ctx = UIGraphicsGetCurrentContext(); 6 7 // 2.绘制内容,拼接路径 8 // 创建贝瑟尔路径,因为里面已经封装好了很多路径 9 UIBezierPath *path = [UIBezierPath bezierPath]; 10 // 绘制一条直线 11 // 设置起点 12 [path moveToPoint:CGPointMake(50, 50)]; 13 // 添加一根线到某个点 14 [path addLineToPoint:CGPointMake(200, 200)]; 15 16 // 3.把拼接好的路径添加到上下文(画板) 17 // UIBezierPath -> CGPath,直接.CGPath 18 CGContextAddPath(ctx, path.CGPath); 19 20 // 4.渲染上下文,就把内容显示到view 21 // 只要跟上下文有关系的东西,都以CGContext开头 22 CGContextStrokePath(ctx);
如果你需要画多条线的话,同样使用上面的方法只是添加两个点(这里是指不连续的),但是只需要使用通一个路径就可以,在一起渲染到图层上下文中
二:绘制曲线
1 // 绘制曲线 2 // 1.获取上下文 3 CGContextRef ctx = UIGraphicsGetCurrentContext(); 4 5 // 2.拼接路径 6 UIBezierPath *path = [UIBezierPath bezierPath]; 7 8 // 设置起点 9 [path moveToPoint:CGPointMake(10, 125)]; 10 11 // 描述曲线 12 [path addQuadCurveToPoint:CGPointMake(240, 125) controlPoint:CGPointMake(125, 240)]; 13 14 [path addLineToPoint:CGPointMake(10, 125)]; 15 16 // 3.添加路径到上下文 17 CGContextAddPath(ctx, path.CGPath); 18 19 // 设置绘图状态,一定要再渲染之前 20 // 设置颜色 21 [[UIColor redColor] setStroke]; 22 23 // 设置线段的宽度 24 CGContextSetLineWidth(ctx, 15); 25 // 设置线段的顶角样式 26 CGContextSetLineCap(ctx, kCGLineCapRound); 27 28 // 设置连接样式 29 CGContextSetLineJoin(ctx, kCGLineJoinRound); 30 31 // 4.渲染上下文 32 CGContextStrokePath(ctx);
三:绘制矩形
1 // 创建路径 2 UIBezierPath *path = [UIBezierPath bezierPath]; 3 4 // 拼接路径 5 [path moveToPoint:CGPointMake(50, 50)]; 6 7 [path addLineToPoint:CGPointMake(200, 200)]; 8 9 // 画线 10 [path stroke]; 11 12 // 描述一个矩形 13 UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 10, 200, 200) cornerRadius:100]; 14 15 [path stroke]; 16 /********************************************************************/ 17 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(10, 10, 200, 100)]; 18 19 [path stroke];
四:绘制扇形
1 2 3 // 1.获取上下文 4 CGContextRef ctx = UIGraphicsGetCurrentContext(); 5 6 // 2.拼接路径 7 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); 8 // 画扇形 9 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:YES]; 10 11 [path addLineToPoint:center]; 12 13 [path closePath]; 14 15 // 3.把路径添加到上下文 16 CGContextAddPath(ctx, path.CGPath); 17 18 // 设置绘图的状态 19 [[UIColor redColor] setFill]; 20 21 [[UIColor greenColor] setStroke]; 22 23 CGContextSetLineWidth(ctx, 5); 24 25 // 4.渲染上下文 26 CGContextDrawPath(ctx, kCGPathFillStroke);
五:画圆弧
1 2 // 画圆弧 3 // Center圆心 4 // radius:半径 5 // startAngle起始角度 6 // endAngle:结束角度 7 // clockwise:Yes 顺时针 No逆时针 8 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); 9 // UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:NO]; 10 // 11 // [path stroke]; 12 13 14 // 画扇形 15 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:YES]; 16 17 [path addLineToPoint:center]; 18 19 // [path addLineToPoint:CGPointMake(self.bounds.size.height * 0.5 + 100, self.bounds.size.height * 0.5)]; 20 // 关闭路径:从路径的终点连接到起点 21 // [path closePath]; 22 // 设置填充颜色 23 [[UIColor redColor] setFill]; 24 25 // 设置描边颜色 26 [[UIColor greenColor] setStroke]; 27 28 // [path stroke]; 29 // 如果路径不是封闭的,默认会关闭路径 30 [path fill];
有的时候我们可能需要自己实现一个指示器(进度条),那么这个时候Quartz 2D就能很简单的实现了
1 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.width * 0.5); 2 CGFloat radius = self.bounds.size.width * 0.5 - 2; 3 CGFloat startA = -M_PI_2; 4 CGFloat endA = -M_PI_2 + _progress * M_PI * 2; 5 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES]; 6 7 [path stroke];
六:绘制饼图
1 // Drawing code 2 3 NSArray *data = @[@25,@25,@20,@30]; 4 5 6 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); 7 CGFloat radius = self.bounds.size.width * 0.5; 8 CGFloat startA = 0; 9 CGFloat endA = 0; 10 CGFloat angle = 0; 11 12 for (NSNumber *num in data) { 13 // 画一个扇形 14 startA = endA; 15 angle = [num intValue] / 100.0 * M_PI * 2; 16 endA = startA + angle; 17 18 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES]; 19 20 [path addLineToPoint:center]; 21 22 // set:同时设置描边和填充颜色 23 [[self randomColor] set]; 24 25 [path fill]; 26 27 }
七:绘制文字
1 NSString *str = @"hello!"; 2 3 // Attributes:属性 4 // 给一个字符串添加属性,可以叫富文本,颜色,字体大小,空心,阴影 5 6 // 利用这个属性字典给文本添加属性 7 NSMutableDictionary *strAttr = [NSMutableDictionary dictionary]; 8 // key,value 9 // 如何找到设置文本的属性key 10 // 描述了字体 11 strAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:50]; 12 13 // 设置描边的颜色和宽度 14 strAttr[NSStrokeWidthAttributeName] = @1; 15 16 strAttr[NSStrokeColorAttributeName] = [UIColor redColor]; 17 18 NSShadow *shadow = [[NSShadow alloc] init]; 19 20 shadow.shadowColor = [UIColor yellowColor]; 21 22 shadow.shadowOffset = CGSizeMake(10, 10); 23 24 shadow.shadowBlurRadius = 5; 25 26 // 阴影 27 strAttr[NSShadowAttributeName] = shadow; 28 29 // 文字颜色 30 strAttr[NSForegroundColorAttributeName] = [UIColor redColor]; 31 32 [str drawAtPoint:CGPointZero withAttributes:strAttr];
这里使用到了文字属性,但是他使用很简单,后面会介绍道关于图文混排在详细介绍他。
注意这两个方法
1 2 // 会自动换行 3 [str drawInRect:rect withAttributes:nil]; 4 5 //不自动换行 6 [str drawAtPoint:CGPointZero withAttributes:nil];
八:绘制图片
1 2 // UIKit框架封装的方法绘制内容 3 4 // 裁剪,rect裁剪的区域 5 6 7 // 文字和图片 8 UIImage *image = [UIImage imageNamed:@"001"]; 9 10 // 绘制的内容跟图片一样大 11 // [image drawAtPoint:CGPointZero]; 12 13 // 裁剪注意点:一定要放在绘图之前 14 // 超出裁剪区域的内容会被裁剪掉 15 UIRectClip(CGRectMake(0, 0, 50, 50)); 16 17 // 把绘制的内容控制到某个区域内 18 // [image drawInRect:CGRectMake(0, 0, 100, 100)]; 19 [image drawAsPatternInRect:rect];
自定义控件之模仿UIImageView
1 - (instancetype)initWithImage:(UIImage *)image 2 { 3 if (self = [super init]) { 4 _image = image; 5 self.frame = CGRectMake(0, 0, image.size.width, image.size.height); 6 } 7 return self; 8 } 9 - (void)setImage:(UIImage *)image 10 { 11 _image = image; 12 [self setNeedsDisplay]; 13 } 14 15 // Only override drawRect: if you perform custom drawing. 16 // An empty implementation adversely affects performance during animation. 17 - (void)drawRect:(CGRect)rect { 18 // Drawing code 19 20 [_image drawInRect:rect]; 21 }
直接使用
iCocosImageView *imageV = [[iCocosImageView alloc] initWithImage:[UIImage imageNamed:@"汽水"]]; [self.view addSubview:imageV];
九:图文上下文栈,有的时候我们在绘制时可能需要保存对应的上下文,在后面再来使用(恢复)
1 // 保存当前上下文的默认状态 2 CGContextSaveGState(ctx); 3 4 // 恢复下上下文状态 5 // 取出之前的保存的状态覆盖掉当前的状态 6 CGContextRestoreGState(ctx);
十:关于矩阵的操作:(矩阵是数学中的一个概念,抱歉我数学不好只能帮你这么多了,哈哈)
1 // 矩阵操作:上下文可以做平移,旋转,缩放,开发中用的比较多是旋转. 2 // 获取跟view相关联的上下文 3 CGContextRef ctx = UIGraphicsGetCurrentContext(); 4 5 // 平移 6 CGContextTranslateCTM(ctx, 150, 200); 7 8 // 旋转 9 CGContextRotateCTM(ctx, M_PI_4); 10 11 // 缩放 12 CGContextScaleCTM(ctx, 0.5, 0.5); 13 14 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, -100, 100, 200)]; 15 16 [[UIColor redColor] set]; 17 18 [path fill];
十一:绘制水印图片-》输出一张带水印的图片
1 // 给一张图片添加文字或者Logo,生成一张新的带有文字或者Logo图片 2 3 4 // 绘制图片到位图上下文,然后再利用位图上下文生成一张新的图片 5 6 7 // 加载图片 8 UIImage *image = [UIImage imageNamed:@"小黄人"]; 9 10 // 1.开启位图上下文 11 // size:上下文的尺寸 12 // opaque:不透明,总结:在上下文中一般都是设置不透明度,控件才是设置透明度 13 // scale: 0表示不缩放 14 UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); 15 16 // 绘制图片 17 [image drawAtPoint:CGPointZero]; 18 19 // 绘制文字 20 NSString *str = @"小码哥"; 21 [str drawAtPoint:CGPointZero withAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]}]; 22 23 // 从上下文内容中生成一张图片 24 image = UIGraphicsGetImageFromCurrentImageContext(); 25 26 // 结束上下文 27 UIGraphicsEndImageContext(); 28 29 // 把图片写入到桌面 30 31 // image -> NSData 32 // 把图片生成一个png格式的二进制数据 33 // png已经高清图片格式 34 // NSData *data = UIImagePNGRepresentation(image); 35 // compressionQuality:图片质量 36 37 NSData *data = UIImageJPEGRepresentation(image, 0.00001); 38 39 [data writeToFile:@"/Users/xiaomage/Desktop/image.jpg" atomically:YES];
十二:图片裁剪:我定义一个UIImage的分类,实现讲一张图片变成一张圆形的图片
1 + (instancetype)imageCirCleWithCircleColor:(UIColor *)color CircleBorder:(CGFloat)border name:(NSString *)imageName 2 { 3 // 裁剪带圆环的图片 4 CGFloat borderWH = border; 5 6 // 加载图片 7 UIImage *image = [UIImage imageNamed:imageName]; 8 9 CGRect bigContextRect = CGRectMake(0, 0, image.size.width + 2 * borderWH, image.size.height + 2 * borderWH); 10 11 // 1.开启位图上下文 12 UIGraphicsBeginImageContextWithOptions(bigContextRect.size, NO, 0); 13 14 // 2.画大圆 15 UIBezierPath *bigCirclePath = [UIBezierPath bezierPathWithOvalInRect:bigContextRect]; 16 17 // 设置大圆颜色 18 [color set]; 19 20 [bigCirclePath fill]; 21 22 // 3.设置裁剪区域 23 // 3.1 先描述裁剪区域 24 UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(borderWH, borderWH, image.size.width, image.size.height)]; 25 [clipPath addClip]; 26 27 // 4.绘制图片 28 [image drawAtPoint:CGPointMake(borderWH, borderWH)]; 29 30 // 5.从上下文内容中生成一张图片 31 image = UIGraphicsGetImageFromCurrentImageContext(); 32 33 // 6.结束上下文 34 UIGraphicsEndImageContext(); 35 36 return image; 37 }
十三:图片截屏
1 // 1.开启位图上下文 2 UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0); 3 4 // 获取当前的位图上下文 5 CGContextRef ctx = UIGraphicsGetCurrentContext(); 6 7 // 2.往上下文中填充内容,把控制器的view的内容画上去,应该是把控制器view上的图层画到上下文上. 8 // 获取控制器view的图层 9 CALayer *layer = self.view.layer; 10 11 // 把layer中内容渲染到上下文中,图层只能渲染,不能绘制 12 // [layer renderInContext:ctx]; 13 [layer drawInContext:ctx]; 14 15 // 3.从上下文中取出图片 16 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 17 18 // 4.结束上下文 19 UIGraphicsEndImageContext(); 20 21 NSData *data = UIImagePNGRepresentation(image); 22 23 [data writeToFile:@"/Users/xiaomage/Desktop/view.png" atomically:YES];
十四:图片截屏,是有手势,根据手指在屏幕上移动的距离形成对角线产生一个半透明的View,在截图对应View区域的图片
1 // 获取下当前的触摸 2 CGPoint curP = [sender locationInView:_imageView]; 3 if (sender.state == UIGestureRecognizerStateBegan) { 4 // 记录下一开始的位置 5 _oriP = curP; 6 } 7 8 // 计算下黑色蒙版的frame 9 CGFloat w = curP.x - _oriP.x; 10 CGFloat h = curP.y - _oriP.y; 11 12 self.cover.frame = CGRectMake(_oriP.x, _oriP.y, w, h); 13 14 15 if (sender.state == UIGestureRecognizerStateEnded) { // 手指抬起 16 17 // 裁剪图片,生成一张新图片 18 19 // 开启位图上下文 20 UIGraphicsBeginImageContextWithOptions(_imageView.bounds.size, NO, 0); 21 22 // 设置裁剪区域 23 UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.cover.frame]; 24 [path addClip]; 25 26 27 // 绘制图片 28 [_imageView.layer renderInContext:UIGraphicsGetCurrentContext()]; 29 30 // 生成图片 31 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 32 33 // 关闭上下文 34 UIGraphicsEndImageContext(); 35 36 _imageView.image = image; 37 38 [self.cover removeFromSuperview]; 39 40 41 }
遮罩View
1 - (UIView *)cover 2 { 3 if (_cover == nil) { 4 UIView *view = [[UIView alloc] init]; 5 6 7 view.backgroundColor = [UIColor blackColor]; 8 view.alpha = 0.5; 9 10 _cover = view; 11 12 [self.view addSubview:view]; 13 14 } 15 return _cover; 16 }
十五:图片擦除:重点Clear方法,当然还有一种方法就是使的对应的区域变成白色
1 // 拖动的时候,擦除图片的某一部分 2 3 // 获取手指的触摸点 4 CGPoint curP = [sender locationInView:sender.view]; 5 6 // 计算擦除的frame 7 CGFloat wh = 30; 8 CGFloat x = curP.x - wh * 0.5; 9 CGFloat y = curP.y - wh * 0.5; 10 11 CGRect frame = CGRectMake(x, y, wh, wh); 12 13 // 开启位图上下文 14 UIGraphicsBeginImageContextWithOptions(sender.view.bounds.size, NO, 0); 15 16 // 获取当前的上下文 17 CGContextRef ctx = UIGraphicsGetCurrentContext(); 18 19 // 把控件上的内容渲染到上下文 20 [sender.view.layer renderInContext:ctx]; 21 22 // 清除上下文中某一部分的内容 23 CGContextClearRect(ctx, frame); 24 25 // 生成一张新的图片 26 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 27 28 // 关闭上下文 29 UIGraphicsEndImageContext(); 30 31 // 重新显示到UIImageView 32 UIImageView *imageV = (UIImageView *)sender.view; 33 34 imageV.image = image;
十六:绘制柱状图
1 NSArray *arr = @[@20,@30,@50]; 2 3 // 获取当前上下文 4 CGContextRef ctx = UIGraphicsGetCurrentContext(); 5 6 // 先算出固定值的变量 7 CGFloat viewW = rect.size.width; 8 CGFloat viewH = rect.size.height; 9 int count = arr.count; 10 CGFloat w = viewW / (2 * count - 1); 11 12 // 不固定的变量,先定义出来,方便后面使用 13 CGFloat x = 0; 14 CGFloat h = 0; 15 CGFloat y = 0; 16 17 for (int i = 0; i < count; i++) { 18 x = i * w * 2; 19 h = viewH * ([arr[i] integerValue] / 100.0); 20 y = viewH - h; 21 // 拼接路径 22 UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)]; 23 24 // 设置绘图状态 25 [[self randomColor] set]; 26 27 // 将路径添加到上下文 28 CGContextAddPath(ctx, path.CGPath); 29 30 // 渲染 31 CGContextFillPath(ctx); 32 33 }
随机颜色
1 /* 颜色有两种常见的表现方式,一个是RGB RGBA 2 RGB是24位颜色,RGBA是32位颜色 3 R,G,B,A四个颜色通道各占8位 4 8个二进制位的取值访问是0~255 5 所以R,G,B,A,每个颜色通道的取值范围是0~255 6 iOS中UIColor colorWith...这个方法传的是浮点型 7 取值范围是0~1 8 所以将0~255的整数值转为0~1的小数 9 比如平时写的120,那就是120/255.0 10 11 */ 12 13 CGFloat r = arc4random_uniform(256)/ 255.0; 14 CGFloat g = arc4random_uniform(256)/ 255.0; 15 CGFloat b = arc4random_uniform(256)/ 255.0; 16 return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
这里关于颜色的介绍清查看笔者之前写的:UIColor深入研究
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4706117.html