ios--Quartz2绘图

来源:互联网 发布:八零网络验证1.3下载 编辑:程序博客网 时间:2024/06/01 10:38
1.什么是Quartz2D:
是一个二维绘图引擎,同时支持iOS和Mac OS系统(跨平台,C语言写的),包含在
core graphICS 框架中,
2.Quartz2D能干什么?
绘制图形:线条,三角形,矩形,圆,弧等
绘制文字
绘制/生成图片
读取生成PDF
截图/裁剪图片
自定义UI控件
3.注意:
Quartz2D是苹果官方的二维绘图引擎,同时支持iOS和Mac OS系统,
Cocos2D(Cocos2D-X,Cocos2D-iphone,Cocos2D-html等)是一个第三方开源的2D游戏框架,做2D游戏的还有Spite Kit,一般3D游戏用unity3D
4.Quartz2D须知:
Quartz2D的API是C语言写的
Quartz2D的API来自Core Graphic框架
数据类型和函数基本都以CG作为前缀
CG类和ontextRef
CGPathRef
CGContextStrokePath(ctx)
... 
5.Quartz2D绘图主要步骤:
1.获取[图形上下文]对象
2.向[图形上下文] 对象中添加[路径]
3.渲染(把[图形上下文]中的图形绘制到对应的设备上)
4.图形上下文CGContextRef:
图形上下文中主要包含如下信息:
1.绘图路径(各种各样的图形)
2.绘图状态(颜色,线宽,样式,旋转,缩放,平移,图片裁剪区域)
3.输出目标(绘制到什么地方去,UIView,图片,PDF,打印机等)
(输出目标可以是PDF文件,bitmap或者显示器的窗口上)
要绘制的图形 -保存->图形上下文-显示->输出目标
相同的一套绘图序列,制定不同的Graphics Context,就可以将相同的图像绘制到不同目标上.
图形上下文对象:
graphICS context:
Bitmap graphICS context
PDF graphICS context
Window  graphICS context
layer graphICS context(UIView控件)
Printer graphICS context
使用Quartz2D绘图:
方式1:直接条用Quartz2D的API进行绘制
代码量稍大
功能全面
步骤:
获取绘图上下文
把图形绘制到图形上下文上
把图形上下文渲染到相应设备上
方式2:调用UIKit 框架封装好的API进行绘图
代码相对简单
只对部分Quartz2D API做了封装
对于没有封装的功能只能调用Quartz2D 原生的API
比如:画图片,文字到控件上(UIKit已经封装好了)
 6.绘图的方式:
  1.使用C语言:
#import "myUIView.h"


@implementation myUIView




- (void)drawRect:(CGRect)rect{
   
   //1.获取上下文
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   //2.拼接路径,同时把路径添加到上下文中
   CGContextMoveToPoint(ctx, 10, 100);//移动到点
   CGContextAddLineToPoint(ctx, 20, 100);//画线到点
   //3.渲染
   CGContextStrokePath(ctx);
}
2.使用C语言+oc语言或swift:
#import "myUIView.h"


@implementation myUIView


- (instancetype)initWithFrame:(CGRect)frame{
   self = [super initWithFrame:frame];
   
   if(self){
       self.backgroundColor = [UIColor blueColor];
       return self;
   }
   return nil;
}




- (void)drawRect:(CGRect)rect{
    
   //1.获取上下文
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   //2.拼接路径
   UIBezierPath *path = [[UIBezierPath alloc] init];
   [path moveToPoint:CGPointMake(0, 0)];
   [path addLineToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height)];
   [path addLineToPoint:CGPointMake(self.bounds.size.width, 0)];
   [path addLineToPoint:CGPointMake(0, self.bounds.size.height)];
   //3.把路径添加到上下文中
   CGContextAddPath(ctx, path.CGPath);
   //4.渲染
   CGContextStrokePath(ctx);
}
@end
3.使用oc语言或swift语言:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [[UIBezierPath alloc] init];
   [path moveToPoint:CGPointMake(0, 0)];\
   [path addLineToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height)];
   //2.渲染
   [path stroke];
}
7.drawRect:
1.绘图代码为什么要写在drawRect方法中?
因为在这个方法中可以获取到正确的上下文
2.drawRect的参数(CGRect)rect含义:
rect是当前view的Bounds(在窗口中得位置)
3.drawRect方法什么时候调用:
1.当这个view第一次显示的时候
2.重绘(相当于TableView的刷新)的时候会调用
4.如何进行重绘:
需要调用需要重绘view的 setNeedsDisplay方法
需要调用需要重绘view的 setNeedsDisplayInRect方法,Rect 制定刷新的区域
5.为什么不能手动调用drawRect方法:
因为要获取到正确的绘图上下文,手动调用的话,系统可能还没创建好上下文
8.绘图练习:
1.绘制线段:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [[UIBezierPath alloc] init];
   [path moveToPoint:CGPointMake(10, 10)];
   [path addLineToPoint:CGPointMake(50, 50)];
   UIBezierPath *path1 = [[UIBezierPath alloc] init];
   [path1 moveToPoint:CGPointMake(30, 10)];
   [path1 addLineToPoint:CGPointMake(70, 80)];
   
   //2.渲染
   [path stroke];
   [path1 stroke];
}
2.画矩形:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 50, 50)];
   //2.渲染
   [path stroke];
}
3.画圆角矩形:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 10, 50, 50) cornerRadius:15];
   //2.渲染
   [path stroke];
}
4.画椭圆(当宽度和高度一样的时候是圆):
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(10, 10, 30, 40)];
   //2.渲染
   [path stroke];
}
5.画弧:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:20 startAngle:M_PI / 3 endAngle:M_PI / 2 clockwise:YES];//参数:圆心,半径,开始位置,结束位置,是否顺时针
   //2.渲染
   [path stroke];
}
6.画圆环:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:20 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
   UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:10 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
   //2.渲染
   [path1 stroke];
   [path stroke];
}
9.绘图的样式:
1.设置线宽:
C语言:
- (void)drawRect:(CGRect)rect{
   //1.创建路径
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   
   CGContextMoveToPoint( ctx, 10, 10);
   CGContextAddLineToPoint(ctx, 50, 50);
   CGContextAddLineToPoint(ctx, 20, 10);
   //设置线条宽度
   CGContextSetLineJoin(ctx, kCGLineJoinBevel);
   CGContextSetLineCap(ctx, kCGLineCapButt);
   CGContextSetLineWidth(ctx, 10);
   //设置颜色
   CGContextSetRGBStrokeColor(ctx, 0, 1, 1, 1);
   CGContextStrokePath(ctx);
}
oc语言或swift:
- (void)drawRect:(CGRect)rect{
   UIBezierPath *path = [[UIBezierPath alloc] init];
   [path moveToPoint:CGPointMake(10, 20)];
   [path addLineToPoint:CGPointMake(50, 60)];
   [path addLineToPoint:CGPointMake(10, 60)];
    [path closePath];//关闭路径
   [path setLineWidth:5];//设置线宽度
   [path setLineCapStyle:kCGLineCapButt];//设置开始和结尾的样式
   [path setLineJoinStyle:kCGLineJoinBevel];//设置连接处的 样式
   //设置颜色
    [[UIColor redColor] setStroke];
   [path stroke];
}






- (void)drawRect:(CGRect)rect{
   UIBezierPath *path = [[UIBezierPath alloc] init];
   [path moveToPoint:CGPointMake(10, 20)];
   [path addLineToPoint:CGPointMake(50, 60)];
   [path addLineToPoint:CGPointMake(10, 60)];
//    [path addLineToPoint:CGPointMake(10, 20)];
   [path closePath];//关闭路径
   [path setLineWidth:2];//设置线宽度
   [path setLineCapStyle:kCGLineCapButt];//设置开始和结尾的样式
   [path setLineJoinStyle:kCGLineJoinBevel];//设置连接处的 样式
   //设置颜色线条
   [[UIColor redColor] setStroke];
   //设置填充
   //    [path fill];
   [[UIColor yellowColor] setFill];//设置填充颜色
   [path fill];
   [path stroke];
}


奇偶填充规则:
当有两个或以上的图形叠加的时候,叠加的部分,如果是叠加了偶数次,则不给填充
- (void)drawRect:(CGRect)rect{
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   UIBezierPath *juxing = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 30, 50)];
   UIBezierPath *yuan = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25, 35) radius:15 startAngle:0 endAngle:M_PI* 2 clockwise:YES];
   UIBezierPath *juxing1 = [UIBezierPath bezierPathWithRect:CGRectMake(5, 5, 50, 50)];
   
   CGContextAddPath(ctx, juxing.CGPath);
   CGContextAddPath(ctx, yuan.CGPath);
   CGContextAddPath(ctx, juxing1.CGPath);
   
   CGContextDrawPath(ctx, kCGPathEOFill);
}
非0环绕数规则:默认的填充方式,从左到右开跨过,+1.从右到左跨过-1.如果最后为0,那么不填充,否则填充
- (void)drawRect:(CGRect)rect{
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   UIBezierPath *yuan = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:50 startAngle:0 endAngle:M_PI* 2 clockwise:YES];
   
   UIBezierPath *yx = [UIBezierPath bezierPathWithArcCenter:CGPointMake(50, 50) radius:30 startAngle:0 endAngle:M_PI * 2 clockwise:NO];
   
   CGContextAddPath(ctx, yuan.CGPath);
   CGContextAddPath(ctx, yx.CGPath);
   CGContextDrawPath(ctx, kCGPathFill);
}
10.绘制饼状图:
.m文件:
#import <UIKit/UIKit.h>


@interface BingtuUIView : UIView
@property(nonatomic,strong) NSArray *data;
@property(nonatomic,strong) NSArray<UIColor *> *colors;
- (instancetype)initWithFrame:(CGRect)frame andData :(NSArray*) data andColors:(NSArray<UIColor*>*) colors;
@end
.h文件:
#import "BingtuUIView.h"


@implementation BingtuUIView


- (instancetype)initWithFrame:(CGRect)frame andData :(NSArray*) data andColors:(NSArray<UIColor*>*) colors{
if(frame.size.height != frame.size.width){
       //如果控件的高度和宽度不一样,则抛出异常
       [NSException raise:@"饼状图的宽度和高度必须一样" format:@"不一样的话,显示不好看"];
   }
   self = [super initWithFrame:frame];
   
   if (self) {
       self.data = data;
       self.colors = colors;
       return self;
   }
   return nil;
}


//模拟数据
- (NSArray *)data{
   if (!_data) {
       _data = @[@30,@20,@20,@30];
       
   }
   return _data;
}


- (NSArray<UIColor *> *)colors{
   if (!_colors) {
       _colors = [NSArray arrayWithObjects:[UIColor redColor],[UIColor whiteColor],[UIColor blueColor],[UIColor orangeColor], nil];
   }
   return _colors;
}




- (void)drawRect:(CGRect)rect{
   int sum = 0;
   for (id num in self.data) {
       sum += [num floatValue];
   }
   float star = 0,end= 0;
   
   for (int i = 0; i< self.data.count;i++) {
        end = 2 * M_PI * ([self.data[i] floatValue] / sum) + star;
       UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius: (self.bounds.size.height < self.bounds.size.width ? self.bounds.size.height:self.bounds.size.width) / 2  startAngle:star endAngle:end clockwise:YES];
       [path addLineToPoint:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2)];
       [self.colors[i] setFill];
       [path fill];
       star = end;
   }
}
@end
使用:
- (BingtuUIView *)bing{
   if (!_bing) {
       _bing = [[BingtuUIView alloc] initWithFrame:CGRectMake(75, 75, 150 , 150) andData:@[@10,@38,@40,@30] andColors:@[[UIColor redColor],[UIColor blueColor],[UIColor orangeColor],[UIColor whiteColor]]];
       _bing.backgroundColor = [UIColor yellowColor];
   }
   return _bing;
}
等学会了画字符串再把字符串加上.


11.绘制柱状图:
.h文件:
#import <UIKit/UIKit.h>


@interface ZhuTuUIView : UIView
@property(nonatomic,strong) NSArray *data;
@property(nonatomic,strong) NSArray<UIColor*> *colors;


- (instancetype)initWithFrame:(CGRect)frame andData:(NSArray *)data andColors:(NSArray<UIColor*>*) colors;
@end
.m文件:
@implementation ZhuTuUIView
- (instancetype)initWithFrame:(CGRect)frame andData:(NSArray *)data andColors:(NSArray<UIColor *> *)colors{
   if(data.count != colors.count){
       [NSException raise:@"" format:@""];
   }
   self = [super initWithFrame:frame];
   if (self) {
       self.data = data;
       self.colors = colors;
       return self;
   }
   return nil;
}


- (void)drawRect:(CGRect)rect{
   //计算出data中的最大数
   float max = [self.data[0] floatValue];
   for (id num in self.data) {
       float numfloat = [num floatValue];
       max = max > numfloat ? max:numfloat;
   }
   
   float kdu =  self.bounds.size.width / (self.data.count * 2 - 1);//100/8=12.5
   
   float value = self.bounds.size.height / max;//100/40 = 2.5
   
   for (int i = 0; i < self.data.count; i++) {
       UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake((i - 1) * 2 * kdu + 2 * kdu , self.bounds.size.height - [self.data[i] floatValue] * value + 20, kdu, [self.data[i] floatValue] * value)];
       [self.colors[i] setFill];
       [path fill];
   }
   
}
@end
使用:
- (ZhuTuUIView *)zhuTu{
   if (!_zhuTu) {
       _zhuTu = [[ZhuTuUIView alloc] initWithFrame:CGRectMake(75, 75, 150 , 100) andData:@[@20,@25,@28,@30,@29,@50] andColors:@[[UIColor redColor],[UIColor blueColor],[UIColor orangeColor],[UIColor whiteColor],[UIColor brownColor],[UIColor blackColor]]];
       _zhuTu.backgroundColor = [UIColor yellowColor];
   }
   return _zhuTu;
}
12.自定义进度条:
.h文件:


#import <UIKit/UIKit.h>


@interface LoadingUIView : UIView
@property(nonatomic,assign) float value;
@property(nonatomic,assign) float maxValue;
@property(nonatomic,strong) UIColor *color;


- (instancetype)initWithFrame:(CGRect)frame addVale:(float) value addMaxVale:(float) maxValue addColor :(UIColor *) color;
@end


.m文件:
#import "LoadingUIView.h"


@interface LoadingUIView ()
@property(nonatomic,strong) UILabel *label;
@end


@implementation LoadingUIView


- (UILabel *)label{
   if(!_label){
       _label = [[UILabel alloc] initWithFrame:CGRectMake(self.bounds.size.width / 2 - 20, self.bounds.size.height / 2 - 10, 40, 20)];
       //_label.backgroundColor = [UIColor colorWithRed:1 green:0 blue:1 alpha:1];
       [_label setTextColor:[UIColor blueColor]];
   }
   return _label;
}


- (instancetype)initWithFrame:(CGRect)frame addVale:(float)value addMaxVale:(float) maxValue  addColor:(UIColor *)color{
   self = [super initWithFrame:frame];
   if(self){
       self.value = value;
       self.color = color;
       self.maxValue = maxValue;
       [self addSubview:self.label];
       return self;
   }
   return nil;
}




- (void)drawRect:(CGRect)rect{
   UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius:(self.bounds.size.height < self.bounds.size.width ? self.bounds.size.height:self.bounds.size.width) / 2 startAngle:0 endAngle: 2 * M_PI * (self.value / self.maxValue) clockwise:YES];
   [path addLineToPoint:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2)];
   self.label.text = [NSString stringWithFormat:@"%0.0lf%%",self.value * 100 / self.maxValue];
   [self.color setFill];
   [path fill];
}
@end
使用:
- (LoadingUIView *)loading{
   if (!_loading) {
       _loading = [[LoadingUIView alloc]initWithFrame:CGRectMake(75, 75, 150 , 150) addVale: 0 addMaxVale:100 addColor:[UIColor redColor]];
       _loading.backgroundColor = [UIColor yellowColor];
   }
   return _loading;
}


- (void)viewDidLoad {
   [super viewDidLoad];
   [self.view addSubview:self.loading];
   
   UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(self.view.bounds.size.width / 6, 300, self.view.bounds.size.width / 3 * 2, 10)];
   slider.value = 0;
   slider.maximumValue = 100;
   slider.minimumValue = 0;
   [slider addTarget:self action:@selector(sliderChage:) forControlEvents:UIControlEventValueChanged];
   [self.view addSubview:slider];
}


- (void) sliderChage:(UISlider*)slider{
   float value = slider.value;
   self.loading.value = value;
   [self.loading setNeedsDisplay];
}


13.矩形操作:
其实是对上下文进行操作:
- (void)drawRect:(CGRect)rect{
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   
   //旋转
   CGContextRotateCTM(ctx, M_PI_4 / 10);
   //缩放
   CGContextScaleCTM(ctx, 0.5, 0.5);
   //平移
   CGContextTranslateCTM(ctx, 20, 60);
   UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 50,  80)];
   
   [[UIColor redColor] setFill];
   
   [path fill];
   
   UIBezierPath *path1 = [[UIBezierPath alloc]init];
   [path1 moveToPoint:CGPointMake(0, 0)];
   [path1 addLineToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height)];
   [path1 stroke];
}
14.图形上下文栈:


15.quartz2d内存管理


16.绘制文字:
- (void)drawRect:(CGRect)rect{
   //文字对象
   NSString *str = @"你好,闻品高";
//    [str drawAtPoint:CGPointMake(10, 10) withAttributes:nil];
   
   [str drawInRect:CGRectMake(5, 50, 80, 50) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:20],NSForegroundColorAttributeName:[UIColor redColor]}];
}
17.绘制图片:
- (void)drawRect:(CGRect)rect{
   UIImage *image = [UIImage imageNamed:@"psb.png"];
   //小图的绘制
//    [image drawAtPoint:CGPointMake(0, 0)];//从某个点开始绘制
//    [image drawInRect:rect];//将图片绘制到某个区域,拉伸的
//    [image drawAsPatternInRect:rect];//将图片绘制到某个区域,平铺
   //大图的绘制
   [image drawAsPatternInRect:rect];
}
18.裁剪上下文的显示区域:
- (void)drawRect:(CGRect)rect{
   UIImage *image = [UIImage imageNamed:@"psb.png"];
   
   CGContextAddArc(UIGraphicsGetCurrentContext(), self.bounds.size.width / 2, self.bounds.size.height / 2, (self.bounds.size.width > self.bounds.size.height ? self.bounds.size.height : self.bounds.size.width) / 2, 0, 2* M_PI, 1);//限定裁剪的区域
   CGContextClip(UIGraphicsGetCurrentContext());//裁剪
   [image drawInRect:rect];
}
19.Bitmap上下文:
1.开启图片的图形上下文


2.绘制简单图形


3.关闭图片的图形上下文


4.保存到沙盒中
1.把图片转为NSDataduix


2.调用data的writertofile方法
//声明属性
@property(nonatomic,strong) UIImageView *imageView;
//加载
- (UIImageView *)imageView{
   if (!_imageView) {
       _imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"psb"]];
       
       _imageView.frame = self.view.bounds;
   }
   
   return _imageView;
}
//添加到view上
    [self.view addSubview:self.imageView];
//点击屏幕时,发生
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
   //开启一个图片类型的上下文
//    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
   UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 1);
   //获取当前上下文
   CGContextRef  ctx = UIGraphicsGetCurrentContext();
   [[UIColor redColor] setStroke];
   CGContextAddArc(ctx, 100, 100, 100, 0, 2 * M_PI, 1);//画圆
   CGContextStrokePath(ctx);//渲染
   UIImage *img = UIGraphicsGetImageFromCurrentImageContext();//输出到图片
   UIGraphicsEndImageContext();//关闭图片图形上下文
   self.imageView.image = img;//添加到界面
   //获取doc目录
   NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES)[0];
   NSString *file = [path stringByAppendingString:@"1.jpg"];
   //保存到沙盒
   NSData * data = UIImageJPEGRepresentation(img, 1);
   [data writeToFile:file atomically:YES];
}






















































   
0 0
原创粉丝点击