您的位置:首页 > 移动开发 > IOS开发

IOS-Quartz2D

2016-02-21 17:41 453 查看
一、画基本图形

//
//  BWView.m
//  IOS_0221_Quartz2D画矩形
//
//  Created by ma c on 16/2/21.
//  Copyright © 2016年 博文科技. All rights reserved.
//

#import "BWView.h"

@implementation BWView
/*
一、什么是Quartz2D
1.Quartz2D是一个二维绘图引擎,同时支持IOS和MAC系统

2.Quartz2D能完成的工作
1>绘制图形:线条\三角形\矩形\圆形\弧
2>绘制文字:
3>绘制\生成图片(图像)
4>读取\生成PDF
5>裁图\裁剪图片
6>自定义UI控件

3.实例
1>裁剪图片(圆形)
2>涂鸦\画板
3>手势解锁

4.最重要的价值
1>自定义UI控件:因为有些UI界面及其复杂,而且比较个性化,用普通的UI控件根本无法实现,
此时可以利用Quartz2D技术将控件内部结构画出来。

5.最重要的概念
1>图形上下文
a.图形上下文(Graghics Context):是一个CGContextRef类型的数据
b.作用:
保留绘图信息,绘图状态
决定绘制的输出目标
绘制好的图形 -> (保存)图形上下文 -> (显示)输出目标
c.相同的一套绘制序列,指定不同的Graghics Context,就可以将相同的图像绘制到不同的
目标上。

2>图形上下文栈
a.将当前的上下文copy一份,保存到栈顶(那个栈叫做”图形上下文栈”)
void CGContextSaveGState(CGContextRef c)
b.将栈顶的上下文出栈,替换掉当前的上下文
void CGContextRestoreGState(CGContextRef c)

6.Quartz2D提供了以下几种类型的Graghics Context:
1>Bitmap Graphics Context
2>PDF Graphics Context
3>Window Graghics Context
4>Layer Graghics Context
5>Printer Graghics Context

7.如何利用Quartz2D自定义view
1>新建一个类,继承自UIView
2>实现 -(void)drawRect:(CGRect)rect方法
a.取得跟当前view相关联的图形上下文
b.绘制相应的图形内容
c.利用图形上下文将绘制的所有内容显示到view上面

8.常识:
1>绘图顺序:后绘制的图形覆盖前一个图形
2>Quartz2D的API是纯C语言
3>Quartz2D的API来自于Core Graphics框架
4>数据类型和函数基本都以CG作为前缀

9.drawRect:中取得的上下文
1>在drawRect:方法中取得上下文后,就可以绘制东西到view上
2>View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,
因此,绘制的东西其实是绘制到view的layer上去了
3>View之所以能显示东西,完全是因为它内部的layer
4>为什么要实现drawRect:方法才能绘图到view上?
因为在drawRect:方法中才能取得跟view相关联的图形上下文
5>drawRect:方法在什么时候被调用?
当view第一次显示到屏幕上时(被加到UIWindow上显示出来)
调用view的setNeedsDisplay或者setNeedsDisplayInRect:时

10.Quartz2D绘图的代码步骤
1>获得图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
2>拼接路径(下面代码是搞一条线段)
CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 100);
3>绘制路径
CGContextStrokePath(ctx); // CGContextFillPath(ctx);

11.常用拼接路径函数
1>新建一个起点
void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
2>添加新的线段到某个点
void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
3>添加一个矩形
void CGContextAddRect(CGContextRef c, CGRect rect)
4>添加一个椭圆
void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
5>添加一个圆弧
void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

12.常用绘制路径函数
1>Mode参数决定绘制的模式
void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)
2>绘制空心路径
void CGContextStrokePath(CGContextRef c)
3>绘制实心路径
void CGContextFillPath(CGContextRef c)
提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

*/

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {

//drawRectangle();
//drawLine();
//drawCircle();
//drawArc();
//drawCurve();

}
///画曲线
void drawCurve()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

CGRect rect = CGRectMake(50, 50, 100, 100);

//中间控制点
CGFloat controlX = rect.size.width * 0.5;
CGFloat controlY = rect.size.height * 0.5;

//当前点
CGFloat marginX = 20;
CGFloat marginY = 10;
CGFloat currentX = controlX - marginX;
CGFloat currentY = controlY - marginY;
CGContextMoveToPoint(ctf, currentX, currentY);

//结束点
CGFloat endX = controlX + marginX;
CGFloat endY = currentY;

//贝塞尔曲线
CGContextAddQuadCurveToPoint(ctf, controlX, controlY, endX, endY);

// 2.渲染
CGContextStrokePath(ctf);
}

///画圆弧
void drawArc()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

// 2.画1/4圆
CGContextMoveToPoint(ctf, 100, 50);
CGContextAddLineToPoint(ctf, 100, 100);

//画圆弧
/*
x/y:圆心
radius:半径
startAngle:开始角度
endAngle:结束角度
clockwise:圆弧的伸展方向(0:顺时针,1:逆时针)
*/
CGContextAddArc(ctf, 100, 50, 50, M_PI_2, M_PI, 0);

// 关闭路径(连接起点和最后一个点)
CGContextClosePath(ctf);

// 设置颜色
[[UIColor redColor] set];

// 3.显示
CGContextFillPath(ctf);

}

///画圆
void drawCircle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

// 2.画圆
CGContextAddEllipseInRect(ctf, CGRectMake(60, 30, 100, 100));

// 3.显示
CGContextStrokePath(ctf);
}

///画线
void drawLine()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

//2.画线

//拷贝当前上下文放到栈中
CGContextSaveGState(ctf);

// 设置线宽
CGContextSetLineWidth(ctf, 5);
// 设置颜色
CGContextSetRGBStrokeColor(ctf, 1, 1, 0.1, 1);
// 设置线段头尾部样式
CGContextSetLineCap(ctf, kCGLineCapRound);
// 设置线段转折点样式
CGContextSetLineJoin(ctf, kCGLineJoinRound);

//设置起点
CGContextMoveToPoint(ctf, 10, 10);
//添加一条线段到(100,100)
CGContextAddLineToPoint(ctf, 100, 100);
// 渲染显示到view上面
CGContextStrokePath(ctf);

//将栈顶的上下文出栈,替换当前的上下文
CGContextRestoreGState(ctf);

//设置起点
CGContextMoveToPoint(ctf, 100, 50);
//添加一条线段到(100,100)
CGContextAddLineToPoint(ctf, 200, 100);
CGContextAddLineToPoint(ctf, 230, 50);
// 渲染显示到view上面
CGContextStrokePath(ctf);
}

///画矩形
void drawRectangle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

// 2.画矩形
CGContextAddRect(ctf, CGRectMake(10, 10, 100, 100));

// 3.绘制图形
//CGContextStrokePath(ctf);
CGContextFillPath(ctf);
}

///画三角形
void drawTriangle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();

// 2.拼接图形(路径)
// 画三角形
CGContextMoveToPoint(ctf, 0, 0);
CGContextAddLineToPoint(ctf, 100, 100);
CGContextAddLineToPoint(ctf, 150, 80);
// 关闭路径(连接起点和最后一个点)
CGContextClosePath(ctf);

// 3.绘制图形
CGContextStrokePath(ctf);

}

@end


二、画文字和图片

//
//  DrawTextAndImgView.m
//  IOS_0221_Quartz2D画矩形
//
//  Created by ma c on 16/2/21.
//  Copyright © 2016年 博文科技. All rights reserved.
//

#import "DrawTextAndImgView.h"

@implementation DrawTextAndImgView

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {

//    drawText();
//    drawImage();
}

///画图片
void drawImage()
{
// 1.取得图片
UIImage *img = [UIImage imageNamed:@"1.jpg"];

// 2.画
//    [img drawAtPoint:CGPointMake(30, 0)];
//    [img drawInRect:CGRectMake(50, 10, 100, 100)];
[img drawAsPatternInRect:CGRectMake(0, 0, 400, 200)];
}

///画文字
void drawText()
{

//方法一 使用OC
NSString *str = @"bowen,哈喽";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSForegroundColorAttributeName] = [UIColor redColor];
dict[NSFontAttributeName] = [UIFont systemFontOfSize:30];
//[str drawAtPoint:CGPointZero withAttributes:nil];
[str drawInRect:CGRectMake(50, 50, 100, 100) withAttributes:dict];

//方法二 使用C
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();
// 2.画文字

// 3.渲染显示
CGContextStrokePath(ctf);
}

@end


三、实用技术

//
//  MatrixOperation.m
//  IOS_0221_Quartz2D画矩形
//
//  Created by ma c on 16/2/21.
//  Copyright © 2016年 博文科技. All rights reserved.
//

#import "MatrixOperation.h"

@implementation MatrixOperation
/*
1.利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化
缩放
void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
旋转
void CGContextRotateCTM(CGContextRef c, CGFloat angle)
平移
void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

2.裁剪
CGContextClip(CGContextRef ctf);

3.重绘,刷帧
[self setNeedsDisplay];

4.屏幕截图
- (void)renderInContext:(CGContextRef)ctx;
调用某个view的layer的renderInContext:方法即可

*/

/*
默认只在第一次显示的时候调用(只能由系统自动调用)
*/
- (void)drawRect:(CGRect)rect {
//    matrix();
//    cut();
//    brush(self.radius);

//    customControl(self.image, rect);

}

///矩阵操作
void matrix()
{
CGContextRef ctf = UIGraphicsGetCurrentContext();

//矩阵操作
//    CGContextScaleCTM(ctf, 0.5, 0.5);
//    CGContextRotateCTM(ctf, M_PI_2 * 0.2);
//    CGContextTranslateCTM(ctf, 50, 50);

CGContextAddRect(ctf, CGRectMake(10, 10, 50, 50));
CGContextAddEllipseInRect(ctf, CGRectMake(100, 40, 100, 100));
CGContextMoveToPoint(ctf, 100, 40);
CGContextAddLineToPoint(ctf, 200, 150);

CGContextStrokePath(ctf);

}

///裁剪
void cut()
{
CGContextRef ctf = UIGraphicsGetCurrentContext();

CGContextAddEllipseInRect(ctf, CGRectMake(100, 100, 50, 50));

//裁剪
CGContextClip(ctf);

CGContextStrokePath(ctf);

UIImage *img = [UIImage imageNamed:@"1.jpg"];
[img drawAtPoint:CGPointMake(100, 100)];
}

///重绘,刷帧
void brush(float radius)
{
CGContextRef ctf = UIGraphicsGetCurrentContext();
CGContextAddArc(ctf, 60, 60, radius, 0, M_PI * 2, 0);
CGContextFillPath(ctf);
}
- (void)setRadius:(float)radius
{
_radius = radius;
//重绘(这个方法内部会重新调用drawRect:方法进行绘制)
[self setNeedsDisplay];
}

///自定义UIImageView控件
void customControl(UIImage *image, CGRect rect)
{
[image drawInRect:rect];
}
- (void)setImage:(UIImage *)image
{
_image = image;
[self setNeedsDisplay];
}

///nib文件加载完毕时调用
- (void)awakeFromNib
{

}

@end


//
//  ViewController.m
//  IOS_0221_Quartz2D画矩形
//
//  Created by ma c on 16/2/21.
//  Copyright © 2016年 博文科技. All rights reserved.
//

#import "ViewController.h"
#import "MatrixOperation.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *imgView;
- (IBAction)valueChange:(UISlider *)sender;
@property (weak, nonatomic) IBOutlet MatrixOperation *brushView;
- (IBAction)clip:(UIButton *)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

//    [self watermark];
[self picCut2];
}
///图片裁剪(圆环)
- (void)picCut2
{
// 1.加载原图
UIImage *oldImage = [UIImage imageNamed:@"me.png"];

// 2.开启上下文
CGFloat borderW = 2; // 圆环的宽度
CGFloat imageW = oldImage.size.width + 2 * borderW;
CGFloat imageH = oldImage.size.height + 2 * borderW;
CGSize imageSize = CGSizeMake(imageW, imageH);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);

// 3.取得当前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// 4.画边框(大圆)
[[UIColor redColor] set];
CGFloat bigRadius = imageW * 0.5; // 大圆半径
CGFloat centerX = bigRadius; // 圆心
CGFloat centerY = bigRadius;
CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);
CGContextFillPath(ctx); // 画圆

// 5.小圆
CGFloat smallRadius = bigRadius - borderW;
CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);
// 裁剪(后面画的东西才会受裁剪的影响)
CGContextClip(ctx);

// 6.画图
[oldImage drawInRect:CGRectMake(borderW, borderW, oldImage.size.width, oldImage.size.height)];

// 7.取图
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

// 8.结束上下文
UIGraphicsEndImageContext();

// 9.显示图片
self.imgView.image = newImage;

// 10.写出文件
NSData *data = UIImagePNGRepresentation(newImage);
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"new.png"];
[data writeToFile:path atomically:YES];
}

///图片裁剪(圆)
- (void)picCut1
{
//1.加载原图
UIImage *image = [UIImage imageNamed:@"me.png"];
//2.开启上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
//3.取得当前上下文
CGContextRef ctf = UIGraphicsGetCurrentContext();
//4.画圆
CGRect circleRect = CGRectMake(0, 0, image.size.width, image.size.height);
CGContextAddEllipseInRect(ctf, circleRect);
//5.按照当前形状裁剪,超出这个形状以外内容不显示
CGContextClip(ctf);
//6.画图
[image drawInRect:circleRect];
//7.取图
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//8.结束
UIGraphicsEndImageContext();
//9.写入文件
NSData *data = UIImagePNGRepresentation(image);
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
[data writeToFile:path atomically:YES];
//10.显示图片
self.imgView.image = newImage;

}

///制作水印
- (void)watermark
{
UIImage *bgImg = [UIImage imageNamed:@"scene.png"];

//上下文:基于位图(bitmap),所有的东西需要绘制到新的图片上去

//1.创建一个基于位图的上下文
UIGraphicsBeginImageContextWithOptions(bgImg.size, NO, 0.0);
//2.画背景
[bgImg drawInRect:CGRectMake(0, 0, bgImg.size.width, bgImg.size.height)];
//3.画水印
UIImage *waterImg = [UIImage imageNamed:@"logo.png"];
CGFloat scale = 0.2;
CGFloat margin = 5;
CGFloat waterW = waterImg.size.width * scale;
CGFloat waterH = waterImg.size.height * scale;
CGFloat waterX = bgImg.size.width - waterW - margin;
CGFloat waterY = bgImg.size.height - waterH - margin;
[waterImg drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
//4.从上下文中取得制作完毕的UIImage对象
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.结束上下文
UIGraphicsEndImageContext();
//6.显示到UIImageView
self.imgView.image = newImage;
//7.将image对象压缩为PNG格式的二进制数据
NSData *data = UIImagePNGRepresentation(newImage);
//8.写入文件
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
[data writeToFile:path atomically:YES];
}
///截图
- (IBAction)clip:(UIButton *)sender {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//1.开启上下文
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
//2.将控制器的view的layer渲染到上下文
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
//3.取出图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
NSData *data = UIImagePNGRepresentation(newImage);
[data writeToFile:@"/Users/mac/Desktop/a.png" atomically:YES];
//4.结束上下文
UIGraphicsEndImageContext();
});
}

///创建自定义ImageView
- (void)createimgView
{
MatrixOperation *imgView = [[MatrixOperation alloc] init];
imgView.frame = CGRectMake(100, 100, 100, 100);
UIImage *img = [UIImage imageNamed:@"1.jpg"];
imgView.image = img;
[self.view addSubview:imgView];
}

- (IBAction)valueChange:(UISlider *)sender {

self.brushView.radius = sender.value;
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: