关闭

11-Quartz2D 二维绘图引擎

标签: IOS开发UI高级2dquartz
318人阅读 评论(0) 收藏 举报
分类:

一、什么是Quartz2D

 Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统

 Quartz 2D能完成的工作:

  绘制图形 : 线条\三角形\矩形\圆\弧等

  绘制文字

  绘制\生成图片(图像)

  读取\生成PDF

  截图\裁剪图片

  自定义UI控件 

二、Quartz2D在iOS开发中的价值

为了便于搭建美观的UI界面,iOS提供了UIKit框架,⾥⾯有各种各样的UI控件 

UILabel:显⽰文字
UIImageView:显示图片
UIButton:同时显示图片和⽂字(能点击)

利⽤UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界⾯

但是,有些UI界面极其复杂、⽽且⽐较个性化,⽤普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子

其实,iOS中⼤部分控件的内容都是通过Quartz2D画出来的
因此,Quartz2D在iOS开发中很重要的⼀个价值是:自定义view(自定义UI控件)

三、图形上下文

图形上下文(Graphics Context):是一个CGContextRef类型的数据

图形上下文的作用:

(1)保存绘图信息、绘图状态
(2)决定绘制的输出目标(绘制到什么地⽅去?) (输出目标可以是PDF⽂文件、Bitmap或者显示器的窗口上)

相同的⼀套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上 

 

四、自定义view

如何利用Quartz2D⾃定义view?(⾃定义UI控件)

如何利用Quartz2D绘制东西到view上?

首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去

其次,那个图形上下⽂必须跟view相关联,才能将内容绘制到view上面


⾃定义view的步骤:

(1)新建⼀个类,继承自UIView

(2)实现-(void)drawRect:(CGRect)rect⽅法.然后在这个⽅方法中 :

         1)取得跟当前view相关联的图形上下文;   UIGraphicsGetCurrentContext()

         2)绘制相应的图形内容

         3)利用图形上下文将绘制的所有内容渲染显示到view上面  CGContextFillPath(ctx);

五、补充说明

1.drawRect:

(1)为什么要实现drawRect:⽅法才能绘图到view上?

因为在drawRect:⽅法中才能取得跟view相关联的图形上下文

(2)drawRect:⽅法在什么时候被调用?

当view第一次显示到屏幕上时(被加到UIWindow上显示出来)

调用view的setNeedsDisplay或者setNeedsDisplayInRect:时 

 

2.Quartz2D须知

Quartz2D的API是纯C语⾔言的
Quartz2D的API来自于Core Graphics框架

数据类型和函数基本都以CG作为前缀

CGContextRef
CGPathRef
CGContextStrokePath(ctx); 

 

3.drawRect:中取得的上下⽂文

在drawRect:方法中取得上下文后,就可以绘制东西到view上

View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了

View之所以能显示东西,完全是因为它内部的layer 


六、代码示例
---------------------------------------------线段|矩形|圆|圆弧---------------------------------------------------------- 
/**贝塞尔线*/
         
- (void)drawCurve:(CGContextRef)ctx
{
   
//设置起点
    CGContextMoveToPoint(ctx,20, 100);
 
    //三次曲线
   
// CGFloat cp1x, //控制点1 x坐标
   
// CGFloat cp1y, //控制点1 y坐标
   
// CGFloat cp2x, //控制点2 x坐标
   
// CGFloat cp2y, //控制点2 y坐标
   
// CGFloat x,  //直线的终点x坐标
   
// CGFloat y  //直线的终点y坐标
   
//添加曲线
   
CGContextAddCurveToPoint(ctx,100,20,20,80,300,50);
   
   
//二次曲线
   
// CGFloat cpx,控制点x坐标
   
// CGFloat cpy,控制点y坐标
   
// CGFloat x, 直线的终点 x坐标
   
// CGFloat y 直线的终点 y坐标
  
CGContextAddQuadCurveToPoint(ctx,5,10,30,20);
   
   
//绘制
   
CGContextDrawPath(ctx,kCGPathStroke);
   
}

/**弧度*/
- (
void)drawArc:(CGContextRef)ctx
{
   
// x\y :圆心
   
// radius :半径
   
// startAngle :开始角度
   
// endAngle :结束角度
   
// clockwise :圆弧的伸展方向(0:顺时针, 1:逆时针)
   
/**绘制图形*/
   
CGContextAddArc(ctx,100,200,20,0,M_PI,1);
   
CGContextClosePath(ctx);
   
   
/**设置属性*/
    [[
UIColorredColor]setStroke];
    [[
UIColororangeColor]setFill];
   
   
/**绘图显示*/
   
CGContextDrawPath(ctx,kCGPathFillStroke);
   
}


/**圆型*/
- (
void)drawCircle:(CGContextRef)ctx
{
   
/**绘制圆形*/
   
CGRect rect = CGRectMake(80,50,200,100);
   
CGContextAddEllipseInRect(ctx, rect);
   
   
/**设置线条色和填充色都显示*/
    [[
UIColorredColor]setFill];
    [[
UIColorblueColor]setStroke];
   
CGContextDrawPath(ctx,kCGPathFillStroke);

}


/**矩形*/
- (
void)drawRec:(CGContextRef)ctx
{
   
/**绘制矩形1.*/
  
CGRect rect = CGRectMake(100,50,200,50);
//    CGContextAddRect(ctx, rect);
   
   
CGContextStrokePath(ctx);
   
   
/**绘制矩形缺点:线条色和填充色不能共存*/
   
    [[
UIColorredColor]setFill];
   
UIRectFrame(rect);
   
UIRectFill(rect);
}

/**线段2*/
- (
void)drawLine2:(CGContextRef)ctx
{
   
/**创建点*/
   
CGPoint p1 = CGPointMake(100,100);
   
CGPoint p2 = CGPointMake(100,150);
   
CGPoint p3 = CGPointMake(300,150);
   
CGPoint p4 = CGPointMake(300,100);
   
CGPoint p5 = CGPointMake(100,100);
   
CGPoint points[] = {p1, p2, p3, p4, p5};
   
   
/**将点加入数组*/
   
CGContextAddLines(ctx, points,5);
   
   
/**线条色和填充色都显示*/
   
/**设置线条色*/
    [[
UIColorredColor]setStroke];
   
/**设置填充色*/
    [[
UIColorgreenColor]setFill];
   
/**绘制*/
   
CGContextDrawPath(ctx,kCGPathFillStroke);

}

--------------------------------------------------------线段--------------------------------------------------------
/**线段1*/
- (
void)drawLine1:(CGContextRef)ctx
{
   
/**2.创建绘制路径*/
   
CGMutablePathRefpath = CGPathCreateMutable();
   
   
/**3.绘制路径*/
   
/**(1)设置起点*/
   
CGPathMoveToPoint(path,NULL,50,50);
   
   
/**(2)绘制线段*/
   
CGPathAddLineToPoint(path,NULL,50,200);
   
CGPathAddLineToPoint(path,NULL,250,250);
   
   
/**4.关闭路径*/
   
CGPathCloseSubpath(path);
   
   
/**5.将路径添加到图形上下文*/
   
CGContextAddPath(ctx, path);
   
   
/**6.设置属性*/
   
CGContextSetRGBStrokeColor(ctx,255/255.0,97/255.0,0/255.0,1);
   
   
CGContextSetLineWidth(ctx,5);
   
    /**7.渲染view上显示*/
    CGContextStrokePath(ctx);
   
   
/**8.释放路径*/
   
CGPathRelease(path);
   
}



--------------------------------------------------------文字|图片-------------------------------------------------------- 
  
   使用OC语法画图不用使用上下文
   
        
   /**画文字*/
    NSString *str =@"哈哈";
    /**在某个点画*/
    //[str drawAtPoint:CGPointZero withAttributes:nil];
   
   NSDictionary *dict =@{NSForegroundColorAttributeName:[UIColorredColor]};
   /**在某个范围画*/
   [str drawInRect:CGRectMake(20,20, 100, 50) withAttributes:dict];

   
    /**取得图片*/
   
UIImage *image = [UIImageimageNamed:@"pig"];
  
     //方式一:指定绘图的位置,大小有图片决定
    [image drawAtPoint:CGPointMake(80,80)];
   
    /**方式二 :拉伸*/
    [image drawInRect:CGRectMake(0,0,60,60)];
   
    /**方式三:平铺*/
    [image drawAsPatternInRect:CGRectMake(0,0, 200,200)];

------------------------------------------------使用CoreGraphics框架----------------------------------------------------
    //1.保存原有的坐标体系
       //将上下文保存一份放到栈中
    CGContextSaveGState(context);
   
   
//2.缩放xY
   
CGContextScaleCTM(context,1, -1);
   
//3.平移图片
   
CGContextTranslateCTM(context,0, -200);
   
   
//4.使用Core Graphic绘制图像
   
CGContextDrawImage(context,CGRectMake(0,0,200,200), img.CGImage);
   
    //5.还原坐标体系
       //将栈顶得上下文出栈 替换当前的上下文
    CGContextRestoreGState(context);


--------------------------------------------------------图片裁剪-------------------------------------------------------- 
为image添加类目 裁剪图片方法

+ (instancetype)circleImageWithName:(NSString*)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor;

+ (instancetype)circleImageWithName:(NSString*)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor
{
   
// 1.加载原图
   
UIImage *oldImage = [UIImageimageNamed:name];
   
   
// 2.开启上下文
   
CGFloat imageW = oldImage.size.width+ 2 * borderWidth;
   
CGFloat imageH = oldImage.size.height+ 2 * borderWidth;
   
CGSize imageSize = CGSizeMake(imageW, imageH);
   
UIGraphicsBeginImageContextWithOptions(imageSize,NO,0.0);
   
   
// 3.取得当前的上下文
   
CGContextRefctx = UIGraphicsGetCurrentContext();
   
   
// 4.画边框(大圆)
    [borderColor
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 - borderWidth;
   
CGContextAddArc(ctx, centerX, centerY, smallRadius,0,M_PI * 2,0);
   
// 裁剪(后面画的东西才会受裁剪的影响)
   
CGContextClip(ctx);
   
   
// 6.画图
    [oldImage
drawInRect:CGRectMake(borderWidth, borderWidth, oldImage.size.width, oldImage.size.height)];
   
   
// 7.取图
   
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
   
   
// 8.结束上下文
   
UIGraphicsEndImageContext();
   
   
return newImage;
}

--------------------------------------------------------打水印-------------------------------------------------------- 
为image添加类目 打水印方法
@interface UIImage (MJ)
/**
 * 
打水印
 *
 * 
@param bg   背景图片
 * 
@param logo 右下角的水印图片
 */

+ (
instancetype)waterImageWithBg:(NSString*)bg logo:(NSString*)logo;
@end
@implementationUIImage (MJ)
+ (
instancetype)waterImageWithBg:(NSString*)bg logo:(NSString*)logo
{
   
UIImage *bgImage = [UIImageimageNamed:bg];
   
   
// 1.创建一个基于位图的上下文(开启一个基于位图的上下文)
   
UIGraphicsBeginImageContextWithOptions(bgImage.size,NO,0.0);
   
   
// 2.画背景
    [bgImage
drawInRect:CGRectMake(0,0, bgImage.size.width, bgImage.size.height)];
   
   
// 3.画右下角的水印
   
UIImage *waterImage = [UIImageimageNamed:logo];
   
CGFloat scale = 0.2;
   
CGFloat margin = 5;
   
CGFloat waterW = waterImage.size.width* scale;
   
CGFloat waterH = waterImage.size.height* scale;
   
CGFloat waterX = bgImage.size.width- waterW - margin;
   
CGFloat waterY = bgImage.size.height- waterH - margin;
    [waterImage
drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
   
   
// 4.从上下文中取得制作完毕的UIImage对象
   
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
   
   
// 5.结束上下文
   
UIGraphicsEndImageContext();
   
   
return newImage;
}
--------------------------------------------------------屏幕截图--------------------------------------------------------
+ (instancetype)captureWithView:(UIView*)view; 
+ (instancetype)captureWithView:(UIView*)view
{
   
// 1.开启上下文
   
UIGraphicsBeginImageContextWithOptions(view.frame.size,NO,0.0);
   
   
// 2.将控制器viewlayer渲染到上下文
    [view.
layerrenderInContext:UIGraphicsGetCurrentContext()];
   
   
// 3.取出图片
   
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
   
   
// 4.结束上下文
   
UIGraphicsEndImageContext();
   
   
return newImage;
}
调用:
- (IBAction)clip {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       
// 1.捕捉
       
UIImage*newImage = [UIImagecaptureWithView:self.view];
       
       
// 2.写文件
       
NSData*data = UIImagePNGRepresentation(newImage);
       
NSString*path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject]stringByAppendingPathComponent:@"new.png"];
        [data
writeToFile:pathatomically:YES];
    });
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:109396次
    • 积分:3585
    • 等级:
    • 排名:第9160名
    • 原创:218篇
    • 转载:65篇
    • 译文:0篇
    • 评论:5条
    最新评论