一、画基本图形

 //
// 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(, , , ); //中间控制点
CGFloat controlX = rect.size.width * 0.5;
CGFloat controlY = rect.size.height * 0.5; //当前点
CGFloat marginX = ;
CGFloat marginY = ;
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, , );
CGContextAddLineToPoint(ctf, , ); //画圆弧
/*
x/y:圆心
radius:半径
startAngle:开始角度
endAngle:结束角度
clockwise:圆弧的伸展方向(0:顺时针,1:逆时针)
*/
CGContextAddArc(ctf, , , , M_PI_2, M_PI, ); // 关闭路径(连接起点和最后一个点)
CGContextClosePath(ctf); // 设置颜色
[[UIColor redColor] set]; // 3.显示
CGContextFillPath(ctf); } ///画圆
void drawCircle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext(); // 2.画圆
CGContextAddEllipseInRect(ctf, CGRectMake(, , , )); // 3.显示
CGContextStrokePath(ctf);
} ///画线
void drawLine()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext(); //2.画线 //拷贝当前上下文放到栈中
CGContextSaveGState(ctf); // 设置线宽
CGContextSetLineWidth(ctf, );
// 设置颜色
CGContextSetRGBStrokeColor(ctf, , , 0.1, );
// 设置线段头尾部样式
CGContextSetLineCap(ctf, kCGLineCapRound);
// 设置线段转折点样式
CGContextSetLineJoin(ctf, kCGLineJoinRound); //设置起点
CGContextMoveToPoint(ctf, , );
//添加一条线段到(100,100)
CGContextAddLineToPoint(ctf, , );
// 渲染显示到view上面
CGContextStrokePath(ctf); //将栈顶的上下文出栈,替换当前的上下文
CGContextRestoreGState(ctf); //设置起点
CGContextMoveToPoint(ctf, , );
//添加一条线段到(100,100)
CGContextAddLineToPoint(ctf, , );
CGContextAddLineToPoint(ctf, , );
// 渲染显示到view上面
CGContextStrokePath(ctf);
} ///画矩形
void drawRectangle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext(); // 2.画矩形
CGContextAddRect(ctf, CGRectMake(, , , )); // 3.绘制图形
//CGContextStrokePath(ctf);
CGContextFillPath(ctf);
} ///画三角形
void drawTriangle()
{
// 1.获得上下文
CGContextRef ctf = UIGraphicsGetCurrentContext(); // 2.拼接图形(路径)
// 画三角形
CGContextMoveToPoint(ctf, , );
CGContextAddLineToPoint(ctf, , );
CGContextAddLineToPoint(ctf, , );
// 关闭路径(连接起点和最后一个点)
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(, , , )];
} ///画文字
void drawText()
{ //方法一 使用OC
NSString *str = @"bowen,哈喽";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSForegroundColorAttributeName] = [UIColor redColor];
dict[NSFontAttributeName] = [UIFont systemFontOfSize:];
//[str drawAtPoint:CGPointZero withAttributes:nil];
[str drawInRect:CGRectMake(, , , ) 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(, , , ));
CGContextAddEllipseInRect(ctf, CGRectMake(, , , ));
CGContextMoveToPoint(ctf, , );
CGContextAddLineToPoint(ctf, , ); CGContextStrokePath(ctf); } ///裁剪
void cut()
{
CGContextRef ctf = UIGraphicsGetCurrentContext(); CGContextAddEllipseInRect(ctf, CGRectMake(, , , )); //裁剪
CGContextClip(ctf); CGContextStrokePath(ctf); UIImage *img = [UIImage imageNamed:@"1.jpg"];
[img drawAtPoint:CGPointMake(, )];
} ///重绘,刷帧
void brush(float radius)
{
CGContextRef ctf = UIGraphicsGetCurrentContext();
CGContextAddArc(ctf, , , radius, , M_PI * , );
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 = ; // 圆环的宽度
CGFloat imageW = oldImage.size.width + * borderW;
CGFloat imageH = oldImage.size.height + * 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, , M_PI * , );
CGContextFillPath(ctx); // 画圆 // 5.小圆
CGFloat smallRadius = bigRadius - borderW;
CGContextAddArc(ctx, centerX, centerY, smallRadius, , M_PI * , );
// 裁剪(后面画的东西才会受裁剪的影响)
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(, , 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(, , bgImg.size.width, bgImg.size.height)];
//3.画水印
UIImage *waterImg = [UIImage imageNamed:@"logo.png"];
CGFloat scale = 0.2;
CGFloat margin = ;
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(, , , );
UIImage *img = [UIImage imageNamed:@"1.jpg"];
imgView.image = img;
[self.view addSubview:imgView];
} - (IBAction)valueChange:(UISlider *)sender { self.brushView.radius = sender.value;
} @end

IOS-Quartz2D的更多相关文章

  1. iOS Quartz2D画图

    对于刚接触Quartz2D的同学来说,先了解 上下文 的概念,再从最基础的画线来具体体验Quartz2D的画图步骤 介绍Quart2D :是苹果官方的二维(平面)绘图引擎,同时支持iOS和macOS系 ...

  2. IOS Quartz2D简介

    Quartz2D 简介( 后续会有相关应用) 第一部分 绘制直线 代码示例: - (void)drawRect:(CGRect)rect{ //获取图形上下文 CGContextRef cxConte ...

  3. iOS——Quartz2D

    0. 复习. 1.基本图形绘制 * 线段(线宽.线段样式) * 矩形(空心.实心.颜色) * 三角形.四边形等形状 1> 说明 - (void)drawRect:(CGRect)rect 什么时 ...

  4. iOS:quartz2D绘图 (动画)

    quartz2D可以用来绘制自己需要的图形,它们绘制出来的是一个静态的图形,那么如何绘制一个动态的图形呢?动态的图形就是动画,所谓动画,其实就是很多张图片在短时间内不停的切换所产生的一种视觉效果.qu ...

  5. IOS Quartz2D 通过UIColor生成图片

    普通生成 示例代码: //这里实现普通生成图片的方法 - (void)drawRect:(CGRect)rect { CGRect cxRect = CGRectMake(, , , ); UIGra ...

  6. IOS Quartz2D自定义view

    @property (nonatomic, weak) UIImageView *imageView; @property (nonatomic, weak) NJImageView *njIv; @ ...

  7. 【原】iOS学习之Quartz2D(1)

    什么是Quartz2D 1.Quartz 2D 是一个二维绘图引擎,同时支持iOS和Mac系统 2.Quartz 2D 能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成 ...

  8. iOS开发——UI进阶篇(十五)Quartz2D介绍

    一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...

  9. iOS开发UI篇—Quartz2D使用(绘制基本图形)

    iOS开发UI篇—Quartz2D使用(绘制基本图形) 一.简单说明 图形上下文(Graphics Context):是一个CGContextRef类型的数据 图形上下文的作用:保存绘图信息.绘图状态 ...

  10. iOS开发UI篇—Quartz2D简单介绍

    iOS开发UI篇—Quartz2D简单介绍 一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\ ...

随机推荐

  1. 前端调试利器——BrowserSync

    此处记录一下踩过的坑 之前看的这个地址:http://www.browsersync.cn/ 也就是 BrowserSync的官网上面关于代理服务器的例子不管怎么试都不行 请看下例子 browser- ...

  2. python中is和==区别

    is比较两个对象的id值是否相等,是否指向同一个内存地址 ==比较的是两个对象的内容是否相等,值是否相等 is运算符比==效率高,在变量和None进行比较时,应该使用is

  3. 2-AMD

    诞生背景1.随着前端逻辑越来越多,项目越来越大,开发大型项目就必须分模块开发2.一切都那么完美,在NodeJs实现后,当人们开始热情的打算把这种实现也用于浏览器时,却发现并不适合.NodeJS应用加载 ...

  4. scp无密码访问scp -i

    网上搜索,可以发现大概有以下情况 1.使用expect交互 2.sshpass 但因为他们都需要安装第三方的软件,不适合我们这样的场景,我们很多时间是绝不允许安装其他软件在客户机上的. 我的场景是在本 ...

  5. 【转】js获取当前日期时间“yyyy-MM-dd HH:MM:SS”

    获取当前的日期时间 格式“yyyy-MM-dd HH:MM:SS”   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function getNowFormatD ...

  6. 前端使用canvas绘制立体三角形

    前端绘制立体效果的三角形的demo 在移动端使用时,需要自适应屏幕.canvas上无法设置rem,所以在canvas外加一个父级元素设置为rem,再将canvas的宽高设置为100% 100%. 如果 ...

  7. HCNP学习笔记之子网划分 VLSM CIDR

    子网划分.VLSM可变长子网掩码.CIDR无类域间路由是学习网络知识或者说是学习路由知识所必备的,但很多朋友说这三者理论性太强了,不好掌握.本文将结合实例讲解子网划分的方法并对VLSM和CIDR进行简 ...

  8. TypeScript 3.3来了!快看看有什么新功能

    翻译:疯狂的技术宅原文:https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript 本文首发微信公众号:jingchen ...

  9. 20145324 Java实验五

    1.运行教材上TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成代码,一人加密后通过TCP发送: 注:加密使用AES或者DES/AES或 ...

  10. Linux下ping命令参数详细解析

    -a Audible ping. #Audible ping. -A Adaptive ping. Interpacket interval adapts to round-trip time, so ...