iOS-绘图之CoreGraphics框架
第一步:先科普一下基础知识:
Core Graphics是基于C的API,可以用于一切绘图操作
Core Graphics 和Quartz 2D的区别
quartz是一个通用的术语,用于描述在iOS和MAC OS X ZHONG 整个媒体层用到的多种技术 包括图形、动画、音频、适配。
Quart 2D 是一组二位绘图和渲染API,Core Graphic会使用到这组API
Quartz Core 专指Core Animation用到的动画相关的库、API和类
点和像素的对比
系统拥有坐标系,如320*480 硬件有retain屏幕和非retain屏:如320*480、640*960
Core Graphics 使用的是系统的坐标系来绘制图片。在分辨率为640*960手机上绘制图片时,实际上Core Graphics 的坐标是320*480。这个时候每个坐标系上的点,实际上拥有两个像素。
图形上下文
Core Graphics 使用图形上下文进行工作,这个上下文的作用像画家的画布一样。
在图形上下文之外是无法绘图的,我们可以自己创建一个上下文,但是性能和内存的使用上,效率是非常低得。
我们可以通过派生一个UIView的子类,获得它的上下文。在UIView中调用drawRect:方法时,会自动准备好一个图形上下文,可以通过调用
UIGraphicsGetCurrentContext()来获取。 因为它是运行期间绘制图片,我们可以动态的做一些额外的操作
Core Graphics的优点
快速、高效,减小应用的文件大小。同时可以自由地使用动态的、高质量的图形图像。 使用Core Graphics,可以创建直线、路径、渐变、文字与图像等内容,并可以做变形处理。
绘制自定义视图
drawRect:是系统的方法,不要从代码里面直接调用 drawRect:,而应该使用setNeedsDisplay重绘.
需要知道的术语
- 路径 path
- 阴影 shadow
- 笔画 stroke
- 剪裁路径 Clip Path
- 线条粗细 Line Width
- 混合模式 Blend Mode
- 填充色 Fill Color
- 当前形变矩阵 Current Transform Matrix
- 线条图案 Line Dash
图形上下文栈
一个图形上下文好比是画布上的一副扁平的图画 执行绘画动作,这些动作是在同一个图层上完成的。 图形上下文不允许将内容分不到多个图层中,如果有需求在不同图层上画,可以考虑使用视图层次结构,创建多个UIView,并将他们作为父视图的子视图
图形上下文栈可以把图形上下文的当前状态保存下来,并在执行一些动作后再次恢复回来
CGContextSaveGState();
CGContextStoreGState();
路径、渐变、文字和图像
路径
1. 使用UIBezierPath创建路径
2. 手动创建路径 moveToPoint addLineToPoint addArcWithCenter addCurveToPoint
渐变
渐变可以在指定方向上,以可变的比率在一系列颜色之间转化
线性渐变:沿着一条定义好了起点和重点的直线方向,呈线性变化。如果这条线有一定角度,线性渐变也会沿相同路径变化
放射渐变:颜色顺着两个原型之间的方向线性变化,这两个园为起始圆和终止圆,每隔圆都有自己的圆心和班级
文字
darwAtPoint
drawInRect
图像
Core Graphics 不会保持图像的长宽比例,Core Graphics会将图像的边界设置为CGrect,不管图片是否变形 darwAtPoint drawInRect
第二步:代码部分:
- (void) drawRect: (CGRect) rect {
UIBezierPath* p = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
[[UIColor blueColor] setFill];
[p fill];
}
- (void) drawRect: (CGRect) rect {
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextFillPath(con);
}
在MyView.h文件中声明如下代码:
@interface MyLayerDelegate : NSObject
@end
@implementation MyLayerDelegate
- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx {
UIGraphicsPushContext(ctx);
UIBezierPath* p = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
[[UIColor blueColor] setFill];
[p fill];
UIGraphicsPopContext();
}
@end
@interface MyView ()
{
MyLayerDelegate* _layerDeleagete;
}
@end
- (void)drawLayer:(CALayer*)lay inContext:(CGContextRef)con {
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextFillPath(con);
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
UIBezierPath* p = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
[[UIColor blueColor] setFill];
[p fill];
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextFillPath(con);
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
第三步:实践部分:
第一种:基本图形绘制
/**
* 什么调用:当你视图第一次显示的时候就会调用
* 作用:绘图
* @param rect = self.bounds
*/
- (void)drawRect:(CGRect)rect
{
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPath];
CGPoint startP = CGPointMake(10, 125);
CGPoint endP = CGPointMake(240, 125);
CGPoint controlP = CGPointMake(125, 0);
[path moveToPoint:startP];
[path addQuadCurveToPoint:endP controlPoint:controlP];
// 3.把路径添加到上下文
CGContextAddPath(ctx, path.CGPath);
// 4.渲染上下文到视图
CGContextStrokePath(ctx);
} - (void)drawLine {
// 1.获取上下文
// CGContextRef CG CoreGraphics Ref 引用
// 目前学的上下文都跟UIGraphics有关,以后想直接获取上下文,直接敲一个UIGraphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.设置绘图信息(拼接路径)
UIBezierPath *path = [UIBezierPath bezierPath]; // 设置起点
[path moveToPoint:CGPointMake(10, 10)];
// 添加一条线到某个点
[path addLineToPoint:CGPointMake(125, 125)];
[path addLineToPoint:CGPointMake(240, 10)];
// 3.把路径添加到上下文
// 直接把UIKit的路径转换成CoreGraphics,CG开头就能转
CGContextAddPath(ctx, path.CGPath);
// 4.把上下文渲染到视图
// Stroke描边
CGContextStrokePath(ctx);
} - (void)draw2Line
{
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPath]; // 设置起点
[path moveToPoint:CGPointMake(10, 125)];
// 添加一条线到某个点
[path addLineToPoint:CGPointMake(230, 125)];
// 设置起点
// [path moveToPoint:CGPointMake(10, 10)];
// 添加一条线到某个点
// [path addLineToPoint:CGPointMake(125, 100)];
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:CGPointMake(10, 10)];
[path1 addLineToPoint:CGPointMake(125, 100)];
// 3.把路径添加到上下文
CGContextAddPath(ctx, path.CGPath);
CGContextAddPath(ctx, path1.CGPath); // 设置绘图状态
// 设置线宽
CGContextSetLineWidth(ctx, 10);
CGContextSetLineCap(ctx, kCGLineCapRound);
// CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);
[[UIColor redColor] set];
// 4.渲染上下文到视图
CGContextStrokePath(ctx);
}
第二种:下载进度条:
- - (void)setProgress:(CGFloat)progress
- {
- _progress = progress;
- self.myLabel.text = [NSString stringWithFormat:@"%.2f%%",progress*100];
- // [self drawRect:self.bounds];
- // 重新绘制
- // 在view上做一个重绘的标记,当下次屏幕刷新的时候,就会调用drawRect.
- [self setNeedsDisplay];
- }
- // Only override drawRect: if you perform custom drawing.
- // An empty implementation adversely affects performance during animation.
- // 当视图显示的时候会调用 默认只会调用一次
- - (void)drawRect:(CGRect)rect
- {
- // 1.获取上下文
- CGContextRef ctx = UIGraphicsGetCurrentContext();
- // 2.拼接路径
- CGPoint center = CGPointMake(50, 50);
- CGFloat radius = 50 - 2;
- CGFloat startA = -M_PI_2;
- CGFloat endA = -M_PI_2 + _progress * M_PI * 2;
- UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
- // 3.把路径添加到上下文
- CGContextAddPath(ctx, path.CGPath);
- // 4.把上下文渲染到视图
- CGContextStrokePath(ctx);
- }
第三种:饼图
- (void)drawRect:(CGRect)rect
{
// Drawing code
NSArray *data = @[@25,@25,@50];
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.拼接路径
CGPoint center = CGPointMake(125, 125);
CGFloat radius = 120;
CGFloat startA = 0;
CGFloat angle = 0;
CGFloat endA = 0; for (NSNumber *number in data) {
// 2.拼接路径
startA = endA;
angle = number.intValue / 100.0 * M_PI * 2;
endA = startA + angle;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
[path addLineToPoint:center]; [[UIColor randomColor] set];
// 把路径添加上下文
CGContextAddPath(ctx, path.CGPath);
// 渲染
CGContextFillPath(ctx); }
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGFloat a = arc4random_uniform(6);
//CGFloat a = arc4random()%6;
NSLog(@"随机数--%f",a);
[self setNeedsDisplay];
} - (void)drawPie
{
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.拼接路径
CGPoint center = CGPointMake(125, 125);
CGFloat radius = 120;
CGFloat startA = 0;
CGFloat angle = 0;
CGFloat endA = 0; // 第一个扇形
angle = 25 / 100.0 * M_PI * 2;
endA = startA + angle;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
[path addLineToPoint:center];
// 添加到上下文
CGContextAddPath(ctx, path.CGPath);
[[UIColor redColor] set]; // 渲染
CGContextFillPath(ctx); // 第二个扇形
startA = endA;
angle = 25 / 100.0 * M_PI * 2;
endA = startA + angle;
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
[path1 addLineToPoint:center];
// 添加到上下文
CGContextAddPath(ctx, path1.CGPath);
[[UIColor greenColor] set];
// 渲染
CGContextFillPath(ctx); // 第三个扇形
startA = endA;
angle = 50 / 100.0 * M_PI * 2;
endA = startA + angle;
UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
[path2 addLineToPoint:center];
// 添加到上下文
CGContextAddPath(ctx, path2.CGPath);
[[UIColor blueColor] set];
// 渲染
CGContextFillPath(ctx);
}
第四种:柱形图
- (void)drawRect:(CGRect)rect
{
NSArray *data = @[@25,@25,@50];
NSInteger count = data.count;
CGFloat w = rect.size.width / (22 * count - 1);
CGFloat h = 0;
CGFloat x = 0;
CGFloat y = 0;
CGFloat viewH = rect.size.height;
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext(); for (int i = 0; i < count; i++) {
h = viewH * [data[i] intValue] / 100.0;
x = 22 * w * i;
y = viewH - h;
// 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)]; // 3.添加路径到上下文
CGContextAddPath(ctx, path.CGPath); [[UIColor randomColor] set]; // 4.渲染
CGContextFillPath(ctx);
}
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setNeedsDisplay];
}
第五种:模仿UIImageView
- (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];
}
第六种:图形上下文线
- (void)drawRect:(CGRect)rect
{
// Drawing code // 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext(); // 把ctx拷贝一份放在栈中
CGContextSaveGState(ctx); // 2.拼接路径(绘图的信息)
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10, 125)];
[path addLineToPoint:CGPointMake(240, 125)]; // 3.路径添加到上下文
CGContextAddPath(ctx, path.CGPath); // 设置绘图的状态
[[UIColor redColor] set];
CGContextSetLineWidth(ctx, 10);
CGContextSetLineCap(ctx, kCGLineCapRound); // 4.渲染
CGContextStrokePath(ctx); // 第二根线
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:CGPointMake(125, 10)];
[path1 addLineToPoint:CGPointMake(125, 240)];
CGContextAddPath(ctx, path1.CGPath); // 把栈顶上下文取出来,替换当前上下文
CGContextRestoreGState(ctx); // 设置绘图的状态
// [[UIColor blackColor] set];
// CGContextSetLineWidth(ctx, 1);
// CGContextSetLineCap(ctx, kCGLineCapButt); // 4.渲染
CGContextStrokePath(ctx); }
第七种:矩形操作
- (void)drawRect:(CGRect)rect {
// Drawing code
// 1.获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext();
// 注意:你的路径一定放在上下文矩阵操作之后
// 平移上下文
CGContextTranslateCTM(ctx, 50, 100);
// 旋转上下文
CGContextRotateCTM(ctx, M_PI_4);
// 缩放上下文
CGContextScaleCTM(ctx, 0.5, 1.2);
// 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, -100, 150, 200)];
// 3.把路径添加到上下文
CGContextAddPath(ctx, path.CGPath);
[[UIColor redColor] set];
// 4.渲染
CGContextFillPath(ctx);
}
iOS-绘图之CoreGraphics框架的更多相关文章
- iOS绘图框架CoreGraphics分析
由于CoreGraphics框架有太多的API,对于初次接触或者对该框架不是十分了解的人,在绘图时,对API的选择会感到有些迷茫,甚至会觉得iOS的图形绘制有些繁琐.因此,本文主要介绍一下iOS的绘图 ...
- 论文第4章:iOS绘图平台的实现
面向移动设备的矢量绘图平台设计与实现 Design and Implementation of Mobile Device-oriented Vector Drawing Platform 引用本论文 ...
- iOS绘图教程 (转,拷贝以记录)
本文是<Programming iOS5>中Drawing一章的翻译,考虑到主题完整性,在翻译过程中我加入了一些书中没有涉及到的内容.希望本文能够对你有所帮助. 转自:http://www ...
- iOS绘图教程
本文是<Programming iOS5>中Drawing一章的翻译,考虑到主题完整性,翻译版本中加入了一些书中未涉及到的内容.希望本文能够对你有所帮助.(本文由海水的味道翻译整理,转载请 ...
- iOS绘图系统UIKit与Core Graphics
概述 iOS主要的绘图系统有UIKit,Core Graphics,Core Animation,Core Image,Open GL等,本片博文主要介绍UIKit与Core Graphics的绘图系 ...
- iOS引入JavaScriptCore引擎框架(二)
为何放弃第一种方案 UIWebView的JSContext获取 上篇中,我们通过简单的kvc获取UIWebVIew的JSContext,但是实际上,apple并未给开发者提供访问UIWebVi ...
- iOS超全开源框架、项目和学习资料汇总(5)AppleWatch、经典博客、三方开源总结篇
完整项目 v2ex – v2ex 的客户端,新闻.论坛.apps-ios-wikipedia – apps-ios-wikipedia 客户端.jetstream-ios – 一款 Uber 的 MV ...
- 【转】iOS超全开源框架、项目和学习资料汇总
iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...
- IOS 中的CoreImage框架
IOS 中的CoreImage框架(framework) - time4cnblogs 时间 2014-03-15 00:24:00 博客园-所有随笔区原文 http://www.cnblogs. ...
- iOS 开发之照片框架详解(2)
一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...
随机推荐
- Weblogic CVE-2018-2894 漏洞复现
0x01 前言 Oracle官方发布了7月份的关键补丁更新CPU(Critical Patch Update),其中针对可造成远程代码执行的高危漏洞 CVE-2018-2894 进行修复:http:/ ...
- Bypass 360主机卫士SQL注入防御(多姿势)
0x00 前言 在服务器客户端领域,曾经出现过一款360主机卫士,目前已停止更新和维护,官网都打不开了,但服务器中依然经常可以看到它的身影.从半年前的测试虚拟机里面,翻出了360主机卫士Apache版 ...
- Kali linux 试用:dnsenum
dnsenum的目的是尽可能收集一个域的信息,它能够通过谷歌或者字典件猜测可能存在的域名,以及对一个网段进行反向查询.它可以查询网站的主机地址信息.域名服务器.mx record(函件交换记录),在域 ...
- Splash autoload() 方法
autoload() 方法可以设置每个页面访问时自动加载的对象,比如自动加载 JavaScript 代码,自动加载 Ajax 代码等等 注意此方法只负责加载 JavaScript/Ajax 代码,不执 ...
- Xcode 7.3 cannot create __weak reference in file using manual reference counting
原帖地址 http://stackoverflow.com/questions/36147625/xcode-7-3-cannot-create-weak-reference-in-file-us ...
- IOS 视频直播/智能家居(一行行敲代码,从零开始)lesson:1整体架构
本文转载至 http://blog.csdn.net/u014011807/article/details/47144027 前段时间由于工作需要做了一个视频直播/智能家居类的应用.算是对iOS音视频 ...
- PHP垃圾回收机制防止内存溢出
PHP语言同其他语言一样,具有垃圾回收机制.那么今天我们要为大家讲解的内容就是关于PHP垃圾回收机制的相关问题.希望对大家有所帮助. 一.PHP 垃圾回收机制(Garbage Collector 简称 ...
- HTML5实现图片预览功能
两种方式实现 URL FileReader Index.jsp文件 <%@page contentType="text/html" pageEncoding="UT ...
- Writing Reentrant and Thread-Safe Code(译:编写可重入和线程安全的代码)
Writing Reentrant and Thread-Safe Code 编写可重入和线程安全的代码 (http://www.ualberta.ca/dept/chemeng/AIX-43/sha ...
- css3整理--rgba
rgba语法: rgba(0, 0, 0,0.5); 第一个参数:R 红色(0-255) 第二个参数:G 绿色(0-255) 第三个参数:B 蓝色(0-255) 第四个参数:透明度(0-1)使用rgb ...