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
相关文章推荐
- IOS-Quartz2D(Paths元素)
- iOS 对象等同性
- iOS编程基础之学习方法篇
- iOS加速计(陀螺仪)的使用
- 蓝牙传送_多点连接 (适用于>iOS7)
- iOS编程基础之基本控件
- iOS友盟消息推送总是推送失败或者token无效
- 利用AVPlayer播放iOS沙盒中的视频
- iOS 相似QQ空间表视图下拉头部视图放大效果实现
- iOS查看沙盒某文件夹下的文件
- iOS 警告收录及科学快速的消除方法
- 面向对象5
- iOS常用全局宏
- 详解IOS中GCD的使用
- iOS银联支付
- iOS开发~CocoaPods使用详细说明
- iOS9+Xcode7免越狱免证书直接调试
- [转] Google 开源 iOS 应用测试工具:EarlGrey
- iOS多线程编程的定义及方法
- iOS NSNotificationCenter 使用姿势详解