iOS开发——图层OC篇&Quartz 2D各种绘制实例
Quartz 2D各种绘制实例
首先说一下,本篇文章只是介绍怎么使用Quartz 2D绘制一些常用的图像效果,关于Quartz和其他相关技术请查看笔者之前写的完整版(Quartz 2D详解)
一:画线
// 1.获取跟当前View相关联的layer上下文(画板) // 总结:目前获取的所有上下文都是以UIGraphics开头 // CGContextRef:上下文类型 // CG:CoreGraphics Ref:引用 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.绘制内容,拼接路径 // 创建贝瑟尔路径,因为里面已经封装好了很多路径 UIBezierPath *path = [UIBezierPath bezierPath]; // 绘制一条直线 // 设置起点 [path moveToPoint:CGPointMake(, )]; // 添加一根线到某个点 [path addLineToPoint:CGPointMake(, )]; // 3.把拼接好的路径添加到上下文(画板) // UIBezierPath -> CGPath,直接.CGPath CGContextAddPath(ctx, path.CGPath); // 4.渲染上下文,就把内容显示到view // 只要跟上下文有关系的东西,都以CGContext开头 CGContextStrokePath(ctx);
如果你需要画多条线的话,同样使用上面的方法只是添加两个点(这里是指不连续的),但是只需要使用通一个路径就可以,在一起渲染到图层上下文中
二:绘制曲线
// 绘制曲线 // 1.获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.拼接路径 UIBezierPath *path = [UIBezierPath bezierPath]; // 设置起点 [path moveToPoint:CGPointMake(, )]; // 描述曲线 [path addQuadCurveToPoint:CGPointMake(, ) controlPoint:CGPointMake(, )]; [path addLineToPoint:CGPointMake(, )]; // 3.添加路径到上下文 CGContextAddPath(ctx, path.CGPath); // 设置绘图状态,一定要再渲染之前 // 设置颜色 [[UIColor redColor] setStroke]; // 设置线段的宽度 CGContextSetLineWidth(ctx, ); // 设置线段的顶角样式 CGContextSetLineCap(ctx, kCGLineCapRound); // 设置连接样式 CGContextSetLineJoin(ctx, kCGLineJoinRound); // 4.渲染上下文 CGContextStrokePath(ctx);
三:绘制矩形
// 创建路径 UIBezierPath *path = [UIBezierPath bezierPath]; // 拼接路径 [path moveToPoint:CGPointMake(, )]; [path addLineToPoint:CGPointMake(, )]; // 画线 [path stroke]; // 描述一个矩形 UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(, , , ) cornerRadius:]; [path stroke]; /********************************************************************/ UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )]; [path stroke];
四:绘制扇形
// 1.获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.拼接路径 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); // 画扇形 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius: startAngle: endAngle:M_PI_2 clockwise:YES]; [path addLineToPoint:center]; [path closePath]; // 3.把路径添加到上下文 CGContextAddPath(ctx, path.CGPath); // 设置绘图的状态 [[UIColor redColor] setFill]; [[UIColor greenColor] setStroke]; CGContextSetLineWidth(ctx, ); // 4.渲染上下文 CGContextDrawPath(ctx, kCGPathFillStroke);
五:画圆弧
// 画圆弧 // Center圆心 // radius:半径 // startAngle起始角度 // endAngle:结束角度 // clockwise:Yes 顺时针 No逆时针 CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); // UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:M_PI_2 clockwise:NO]; // // [path stroke]; // 画扇形 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius: startAngle: endAngle:M_PI_2 clockwise:YES]; [path addLineToPoint:center]; // [path addLineToPoint:CGPointMake(self.bounds.size.height * 0.5 + 100, self.bounds.size.height * 0.5)]; // 关闭路径:从路径的终点连接到起点 // [path closePath]; // 设置填充颜色 [[UIColor redColor] setFill]; // 设置描边颜色 [[UIColor greenColor] setStroke]; // [path stroke]; // 如果路径不是封闭的,默认会关闭路径 [path fill];
有的时候我们可能需要自己实现一个指示器(进度条),那么这个时候Quartz 2D就能很简单的实现了
CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.width * 0.5); CGFloat radius = self.bounds.size.width * ; CGFloat startA = -M_PI_2; CGFloat endA = -M_PI_2 + _progress * M_PI * ; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES]; [path stroke];
六:绘制饼图
// Drawing code NSArray *data = @[@,@,@,@]; CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5); CGFloat radius = self.bounds.size.width * 0.5; CGFloat startA = ; CGFloat endA = ; CGFloat angle = ; for (NSNumber *num in data) { // 画一个扇形 startA = endA; angle = [num intValue] / ; endA = startA + angle; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES]; [path addLineToPoint:center]; // set:同时设置描边和填充颜色 [[self randomColor] set]; [path fill]; }
七:绘制文字
NSString *str = @"hello!"; // Attributes:属性 // 给一个字符串添加属性,可以叫富文本,颜色,字体大小,空心,阴影 // 利用这个属性字典给文本添加属性 NSMutableDictionary *strAttr = [NSMutableDictionary dictionary]; // key,value // 如何找到设置文本的属性key // 描述了字体 strAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:]; // 设置描边的颜色和宽度 strAttr[NSStrokeWidthAttributeName] = @; strAttr[NSStrokeColorAttributeName] = [UIColor redColor]; NSShadow *shadow = [[NSShadow alloc] init]; shadow.shadowColor = [UIColor yellowColor]; shadow.shadowOffset = CGSizeMake(, ); shadow.shadowBlurRadius = ; // 阴影 strAttr[NSShadowAttributeName] = shadow; // 文字颜色 strAttr[NSForegroundColorAttributeName] = [UIColor redColor]; [str drawAtPoint:CGPointZero withAttributes:strAttr];
这里使用到了文字属性,但是他使用很简单,后面会介绍道关于图文混排在详细介绍他。
注意这两个方法
// 会自动换行 [str drawInRect:rect withAttributes:nil]; //不自动换行 [str drawAtPoint:CGPointZero withAttributes:nil];
八:绘制图片
// UIKit框架封装的方法绘制内容 // 裁剪,rect裁剪的区域 // 文字和图片 UIImage *image = [UIImage imageNamed:"]; // 绘制的内容跟图片一样大 // [image drawAtPoint:CGPointZero]; // 裁剪注意点:一定要放在绘图之前 // 超出裁剪区域的内容会被裁剪掉 UIRectClip(CGRectMake(, , , )); // 把绘制的内容控制到某个区域内 // [image drawInRect:CGRectMake(0, 0, 100, 100)]; [image drawAsPatternInRect:rect];
自定义控件之模仿UIImageView
- (instancetype)initWithImage:(UIImage *)image { if (self = [super init]) { _image = image; self.frame = CGRectMake(, , image.size.width, image.size.height); } return self; } - (void)setImage:(UIImage *)image { _image = image; [self setNeedsDisplay]; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code [_image drawInRect:rect]; }
直接使用
iCocosImageView *imageV = [[iCocosImageView alloc] initWithImage:[UIImage imageNamed:@"汽水"]]; [self.view addSubview:imageV];
九:图文上下文栈,有的时候我们在绘制时可能需要保存对应的上下文,在后面再来使用(恢复)
// 保存当前上下文的默认状态 CGContextSaveGState(ctx); // 恢复下上下文状态 // 取出之前的保存的状态覆盖掉当前的状态 CGContextRestoreGState(ctx);
十:关于矩阵的操作:(矩阵是数学中的一个概念,抱歉我数学不好只能帮你这么多了,哈哈)
// 矩阵操作:上下文可以做平移,旋转,缩放,开发中用的比较多是旋转. // 获取跟view相关联的上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 平移 CGContextTranslateCTM(ctx, , ); // 旋转 CGContextRotateCTM(ctx, M_PI_4); // 缩放 CGContextScaleCTM(ctx, 0.5, 0.5); UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-, -, , )]; [[UIColor redColor] set]; [path fill];
十一:绘制水印图片-》输出一张带水印的图片
// 给一张图片添加文字或者Logo,生成一张新的带有文字或者Logo图片 // 绘制图片到位图上下文,然后再利用位图上下文生成一张新的图片 // 加载图片 UIImage *image = [UIImage imageNamed:@"小黄人"]; // 1.开启位图上下文 // size:上下文的尺寸 // opaque:不透明,总结:在上下文中一般都是设置不透明度,控件才是设置透明度 // scale: 0表示不缩放 UIGraphicsBeginImageContextWithOptions(image.size, NO, ); // 绘制图片 [image drawAtPoint:CGPointZero]; // 绘制文字 NSString *str = @"小码哥"; [str drawAtPoint:CGPointZero withAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]}]; // 从上下文内容中生成一张图片 image = UIGraphicsGetImageFromCurrentImageContext(); // 结束上下文 UIGraphicsEndImageContext(); // 把图片写入到桌面 // image -> NSData // 把图片生成一个png格式的二进制数据 // png已经高清图片格式 // NSData *data = UIImagePNGRepresentation(image); // compressionQuality:图片质量 NSData *data = UIImageJPEGRepresentation(image, 0.00001); [data writeToFile:@"/Users/xiaomage/Desktop/image.jpg" atomically:YES];
十二:图片裁剪:我定义一个UIImage的分类,实现讲一张图片变成一张圆形的图片
+ (instancetype)imageCirCleWithCircleColor:(UIColor *)color CircleBorder:(CGFloat)border name:(NSString *)imageName { // 裁剪带圆环的图片 CGFloat borderWH = border; // 加载图片 UIImage *image = [UIImage imageNamed:imageName]; CGRect bigContextRect = CGRectMake(, , image.size.width + * borderWH, image.size.height + * borderWH); // 1.开启位图上下文 UIGraphicsBeginImageContextWithOptions(bigContextRect.size, NO, ); // 2.画大圆 UIBezierPath *bigCirclePath = [UIBezierPath bezierPathWithOvalInRect:bigContextRect]; // 设置大圆颜色 [color set]; [bigCirclePath fill]; // 3.设置裁剪区域 // 3.1 先描述裁剪区域 UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(borderWH, borderWH, image.size.width, image.size.height)]; [clipPath addClip]; // 4.绘制图片 [image drawAtPoint:CGPointMake(borderWH, borderWH)]; // 5.从上下文内容中生成一张图片 image = UIGraphicsGetImageFromCurrentImageContext(); // 6.结束上下文 UIGraphicsEndImageContext(); return image; }
十三:图片截屏
// 1.开启位图上下文 UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, ); // 获取当前的位图上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.往上下文中填充内容,把控制器的view的内容画上去,应该是把控制器view上的图层画到上下文上. // 获取控制器view的图层 CALayer *layer = self.view.layer; // 把layer中内容渲染到上下文中,图层只能渲染,不能绘制 // [layer renderInContext:ctx]; [layer drawInContext:ctx]; // 3.从上下文中取出图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 4.结束上下文 UIGraphicsEndImageContext(); NSData *data = UIImagePNGRepresentation(image); [data writeToFile:@"/Users/xiaomage/Desktop/view.png" atomically:YES];
十四:图片截屏,是有手势,根据手指在屏幕上移动的距离形成对角线产生一个半透明的View,在截图对应View区域的图片
// 获取下当前的触摸 CGPoint curP = [sender locationInView:_imageView]; if (sender.state == UIGestureRecognizerStateBegan) { // 记录下一开始的位置 _oriP = curP; } // 计算下黑色蒙版的frame CGFloat w = curP.x - _oriP.x; CGFloat h = curP.y - _oriP.y; self.cover.frame = CGRectMake(_oriP.x, _oriP.y, w, h); if (sender.state == UIGestureRecognizerStateEnded) { // 手指抬起 // 裁剪图片,生成一张新图片 // 开启位图上下文 UIGraphicsBeginImageContextWithOptions(_imageView.bounds.size, NO, ); // 设置裁剪区域 UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.cover.frame]; [path addClip]; // 绘制图片 [_imageView.layer renderInContext:UIGraphicsGetCurrentContext()]; // 生成图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 关闭上下文 UIGraphicsEndImageContext(); _imageView.image = image; [self.cover removeFromSuperview]; }
遮罩View
- (UIView *)cover { if (_cover == nil) { UIView *view = [[UIView alloc] init]; view.backgroundColor = [UIColor blackColor]; view.alpha = 0.5; _cover = view; [self.view addSubview:view]; } return _cover; }
十五:图片擦除:重点Clear方法,当然还有一种方法就是使的对应的区域变成白色
// 拖动的时候,擦除图片的某一部分 // 获取手指的触摸点 CGPoint curP = [sender locationInView:sender.view]; // 计算擦除的frame CGFloat wh = ; CGFloat x = curP.x - wh * 0.5; CGFloat y = curP.y - wh * 0.5; CGRect frame = CGRectMake(x, y, wh, wh); // 开启位图上下文 UIGraphicsBeginImageContextWithOptions(sender.view.bounds.size, NO, ); // 获取当前的上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 把控件上的内容渲染到上下文 [sender.view.layer renderInContext:ctx]; // 清除上下文中某一部分的内容 CGContextClearRect(ctx, frame); // 生成一张新的图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 关闭上下文 UIGraphicsEndImageContext(); // 重新显示到UIImageView UIImageView *imageV = (UIImageView *)sender.view; imageV.image = image;
十六:绘制柱状图
NSArray *arr = @[@,@,@]; // 获取当前上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 先算出固定值的变量 CGFloat viewW = rect.size.width; CGFloat viewH = rect.size.height; int count = arr.count; CGFloat w = viewW / ( * count - ); // 不固定的变量,先定义出来,方便后面使用 CGFloat x = ; CGFloat h = ; CGFloat y = ; ; i < count; i++) { x = i * w * ; h = viewH * ([arr[i] integerValue] / 100.0); y = viewH - h; // 拼接路径 UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)]; // 设置绘图状态 [[self randomColor] set]; // 将路径添加到上下文 CGContextAddPath(ctx, path.CGPath); // 渲染 CGContextFillPath(ctx); }
随机颜色
/* 颜色有两种常见的表现方式,一个是RGB RGBA RGB是24位颜色,RGBA是32位颜色 R,G,B,A四个颜色通道各占8位 8个二进制位的取值访问是0~255 所以R,G,B,A,每个颜色通道的取值范围是0~255 iOS中UIColor colorWith...这个方法传的是浮点型 取值范围是0~1 所以将0~255的整数值转为0~1的小数 比如平时写的120,那就是120/255.0 */ CGFloat r = arc4random_uniform()/ 255.0; CGFloat g = arc4random_uniform()/ 255.0; CGFloat b = arc4random_uniform()/ 255.0; return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
这里关于颜色的介绍清查看笔者之前写的:UIColor深入研究
iOS开发——图层OC篇&Quartz 2D各种绘制实例的更多相关文章
- iOS开发——图层OC篇&UIColor深入研究(CGColor,CIColor)
UIColor深入研究(CGColor,CIColor) 由于跟人比较喜欢研究关于图层与动画方面的技术,正打算看看别人写的好东西,就遇到了好几个问题, 第一:UIClor类方法的使用 就是关于UICo ...
- iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController) 前面我们介绍了StoryBoard这个新技术,和纯技术 ...
- iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController) 这里我们就直接上实例: 一:新建一个项目singleV ...
- iOS开发——动画OC篇&知识点总结
图层与动画知识点总结 1.Core Animation 非娱乐类的软件都会用到的动画,操作简单. 2.Quartz 2D绘图 是一个2D绘图引擎. (1) 绘图Context是一个绘图的目标对象,定义 ...
- iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)
单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...
- iOS开发——实战OC篇&环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)
环境搭建之StoryBoard(玩转UINavigationController与UITabBarController) 研究了这么就IOS开发,都没有所处一个像样或者自己忙一点的项目.最近自 ...
- iOS开发——控制器OC篇&UINavigationController&UITabBarController详解
UINavigationController&UITabBarController详解 一:UINavigationController 控制器的属性: UINavigationControl ...
- iOS开发——多线程OC篇&多线程详解
多线程详解 前面介绍了多线程的各种方式及其使用,这里补一点关于多线程的概念及相关技巧与使用,相信前面不懂的地方看了这里之后你就对多线程基本上没有什么问题了! 1——首先ios开发多线程中必须了解的概念 ...
- iOS开发——多线程OC篇&多线程总结
多线程总结 //1.NSThread /** 优点:NSThread 比其他两个轻量级. 缺点:需要自己管理线程的生命周期,线程同步,线程同步时对数据的加锁会有一定的系统开销. cocoa给我提供了两 ...
随机推荐
- ListView蛮好用
知识点如下: 1. ListView的基本用法 2. ArrayAdapter和SimpleAdapter的用法 3. OnScrollListener 和 OnItemClickListener 4 ...
- 【重读】The C++ Programming Language/C++编程语言(一)
最近在写C++系列的文章,翻出以前看过的 C++之父Bjarne Stroustrup的书.再一次,竟然又有新的领悟.现在看来,这不是一本只讲C++的书,对于程序设计/开发,以及如何学习开发知识都有所 ...
- ESP8266 TCP传输AT指令顺序
); //复位 ret = ESP8266_Cmd ( );//测试AT启动 ret = ESP8266_Cmd ( );//选择WIFI应用模式softAP+station //ret = ESP8 ...
- 串口 COM口 USB-TTL RS-232 RS-485 不同标准 区别 释疑
http://blog.sina.com.cn/s/blog_6566538d0100r7p8.html Point (所有要点都在这,请仔细阅读): 1.串口.COM口是指的物理接口形式(硬件).而 ...
- joj 2453 candy 网络流建图的题
Problem D: Candy As a teacher of a kindergarten, you have many things to do during a day, one of whi ...
- Top 7 Myths about HTTPS
Myth #7 – HTTPS Never Caches People often claim that HTTPS content is never cached by the browser; p ...
- springMVC+JAP整合彻底摆脱persistence.xml配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- fastcgi 分布式
以lighttpd fastcgi写一下自己对fastcgi分布式的理解. 假设一台机器A上运行lighttpd,在这台主机上只是对请求进行分发. 而在其他多台机器上运行多个fastcgi进程,用来接 ...
- 在jybot下跑Selenium2Library
应用场景:项目组要将原有SeleniumLibrary写的脚本切换到Selenium2Library(后称S2L)下,但是原来有很多Java写的库,综合考虑认为还是在Jython下跑比较合适.但是安装 ...
- 用Javascript编写Chrome浏览器插件
原文:http://homepage.yesky.com/62/11206062.shtml 用Javascript编写Chrome浏览器插件 2010-04-12 07:30 来源:天极网软件频道 ...