绘图-Core Graphics

前言

CGContext又叫图形上下文,相当于一块画布,以堆栈形式存放,只有在当前context上绘图才有效。iOS有分多种图形上下文,其中UIView自带提供的在drawRect:方法中通过UIGraphicsGetCurrentContext获取,还有专门为图片处理的context,UIGraphicsBeginImageContext函数生成,还有pdf的context等等。

Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。iOS支持两套图形API族:Core Graphics/QuartZ 2D 和OpenGL ES。前者提供了低级别、轻量级、高保真度的2D渲染。该框架可以用于基于路径的绘图、变换、颜色管理、脱屏渲染,模板、渐变、遮蔽、图像数据管理、图像的创建、遮罩以及PDF文档的创建、显示和分析。

Quart 2D 是一组二位绘图和渲染API,Core Graphic会使用到这组API

这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。

顺便说一下,有代码工具 PaintCode 可以生成相应的 Core Graphics 代码,直接拖进工程中就可以使用,可以大幅加快开发进程,当然是你先学会使用PaintCode才行

简述

绘图的步骤:(在drawRect函数中) 1.获取绘图上下文 2.创建并设置路径 3.将路径添加到上下文 4.设置上下文状态 5.绘制路径 6.释放路径

在使用Core Graphics 时有许多方式获得一个图形上下文,这里我介绍两种最为常用的获取方法 第一种方法就是创建一个图片类型的上下文。 调用UIGraphicsBeginImageContextWithOptions函数就可获得用来处理图片的图形上下文。利用该上下文,你就可以在其上进行绘图,并生成图片。 调用UIGraphicsGetImageFromCurrentImageContext函数可从当前上下文中获取一个UIImage对象。记住在你所有的绘图操作后别忘了调用UIGraphicsEndImageContext函数关闭图形上下文。

第二种方法是利用cocoa为你生成的图形上下文。 当你子类化了一个UIView并实现了自己的drawRect:方法后,一旦drawRect:方法被调用,Cocoa就会为你创建一个图形上下文,此时你对图形上下文的所有绘图操作都会显示在UIView上。

Core Graphics 里面的类文件众多:

Paste_Image.png

让我们来看一下CGContext.h 里面的方法:

CGContextRef context = UIGraphicsGetCurrentContext(); 设置上下文                
CGContextMoveToPoint 开始画线
CGContextAddLineToPoint 画直线

CGContextAddEllipseInRect 画一椭圆
CGContextSetLineCap 设置线条终点形状        #三个枚举值
#1.kCGLineCapButt该属性值指定不绘制端点, 线条结尾处直接结束。这是默认值。
#2.kCGLineCapRound该属性值指定绘制圆形端点, 线条结尾处绘制一个直径为线条宽度的半圆
#3.kCGLineCapSquare该属性值指定绘制方形端点。线条结尾处绘制半个边长为线条宽度的正方形。需要说明的是,
#这种形状的端点与“butt”形状的端点十分相似,只是采用这种形式的端点的线条略长一点而已
CGContextSetLineDash 画虚线
CGContextAddRect 画一方框
CGContextStrokeRect 指定矩形
CGContextStrokeRectWithWidth 指定矩形线宽度
CGContextStrokeLineSegments 一些直线


CGContextAddArc 画已曲线 前俩店为中心 中间俩店为起始弧度 最后一数据为0则顺时针画 1则逆时针
CGContextAddArcToPoint(context,0,0, 2, 9, 40);//先画俩条线从point 到 弟1点 , 从弟1点到弟2点的线  切割里面的圆   
CGContextSetShadowWithColor 设置阴影   
CGContextSetRGBFillColor 这只填充颜色
CGContextSetRGBStrokeColor 画笔颜色设置    
CGContextSetFillColorSpace 颜色空间填充   
CGConextSetStrokeColorSpace 颜色空间画笔设置
CGContextFillRect 补充当前填充颜色的rect
CGContextSetAlaha 透明度


CGContextTranslateCTM 改变画布位置
CGContextSetLineWidth 设置线的宽度
CGContextAddRects 画多个线
CGContextAddQuadCurveToPoint 画曲线
CGContextStrokePath 开始绘制图片
CGContextDrawPath 设置绘制模式
CGContextClosePath 封闭当前线路
CGContextTranslateCTM(context, 0, rect.size.height);    
CGContextScaleCTM(context, 1.0, -1.0);反转画布      
CGContextSetInterpolationQuality 背景内置颜色质量等级 
CGImageCreateWithImageInRect 从原图片中取小图


字符串的 写入可用  nsstring本身的画图方法 
- (CGSize)drawInRect:  (CGRect)rect withFont:(UIFont *)font lineBreakMode:
(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment;来写进去即可

对图片放大缩小的功能就是慢了点  
UIGraphicsBeginImageContext(newSize);    
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();


CGColorGetComponents() 返回颜色的各个直 以及透明度 可用只读const float 来接收  是个数组


画图片 
CGImageRef image= CGImageRetain(img.CGImage);   
CGContextDrawImage(context, CGRectMake(10.0, height -100.0, 90.0, 90.0), image);


 实现逐变颜色填充方法
 CGContextClip(context);   
 CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();   
 CGFloat colors[] =    {  204.0 / 255.0, 224.0 / 255.0, 244.0 /  255.0, 1.00,       
     29.0 / 255.0, 156.0 / 255.0, 215.0 / 255.0, 1.00, 0.0 /     
     255.0,  50.0 / 255.0, 126.0 / 255.0, 1.00,    
  };  
 CGGradientRef gradient =CGGradientCreateWithColorComponents (rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));   
 CGColorSpaceRelease(rgb);             
 CGContextDrawLinearGradient(context,gradient,CGPointMake(0.0,0.0),CGPointMake(0.0,self.frame.size.height), kCGGradientDrawsBeforeStartLocation);

 **注意释放掉对象,已释放内存**
 注:  画完图后,必须    
 先用CGContextStrokePath来描线,即形状    
 后用CGContextFillPath来填充形状内的颜色.


 填充一个路径的时候,路径里面的子路径都是独立填充的。
 假如是重叠的路径,决定一个点是否被填充,有两种规则
 1,nonzero winding number rule:非零绕数规则,假如一个点被从左到右跨过,计数器+1,从右到左跨过,计数器-1,最后,如果结果是0,那么不填充,如果是非零,那么填充。
 2,even-odd rule: 奇偶规则,假如一个点被跨过,那么+1,最后是奇数,那么要被填充,偶数则不填充,和方向没有关系。


Function
Description  
CGContextEOFillPath 使用奇偶规则填充当前路径     
CGContextFillPath 使用非零绕数规则填充当前路径
CGContextFillRect 填充指定的矩形 
CGContextFillRects 填充指定的一些矩形 
CGContextFillEllipseInRect 填充指定矩形中的椭圆 
CGContextDrawPath 两个参数决定填充规则,kCGPathFill表示用非零绕数规则,kCGPathEOFill表示用奇偶规则,kCGPathFillStroke表示填充, kCGPathEOFillStroke表示描线,不是填充


设置当一个颜色覆盖上另外一个颜色,两个颜色怎么混合
默认方式是   
result = (alpha * foreground) + (1 - alpha) * background
CGContextSetBlendMode :设置blend mode.
CGContextSaveGState :保存blend mode.
CGContextRestoreGState:在没有保存之前,用这个函数还原blend mode.
CGContextSetBlendMode 混合俩种颜色

让我们来看一下CGPath.h 里面的方法:

Paste_Image.png

Creating and Managing Paths

CGPathCreateMutable  创建一个可变的图形路径。
CGPathCreateWithEllipseInRect   创建一个椭圆的不可变路径。
CGPathCreateWithRect    创建一个矩形的不可变路径。
CGPathCreateWithRoundedRect 创建一个圆角矩形的不可变路径。
CGPathCreateCopy    创建一个图形路径的不可变副本。
CGPathCreateCopyByTransformingPath  创建由变换矩阵变换的图形路径的不可变副本。
CGPathCreateCopyByDashingPath  创建另一个路径的虚线副本。
CGPathCreateCopyByStrokingPath   创建另一个路径的实线副本。
CGPathCreateMutableCopy    创建一个现有的图形路径可复制。
CGPathCreateMutableCopyByTransformingPath  创建一个图形路径的变换矩阵将可变副本。
CGPathRelease      减少图形路径
CGPathRetain        递增一个图形路径的保留计数。

Modifying Quartz Paths

CGPathAddArc   追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddRelativeArc   追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddArcToPoint  追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddCurveToPoint  //绘制三次贝塞尔曲线
CGPathAddLines  追加新的线段图形路径数组的一个可变的。
CGPathAddLineToPoint   追加一条线段一个可变的图形路径。
CGPathAddPath   添加一个路径到一个可变的图形路径。
CGPathAddQuadCurveToPoint   //绘制二次贝塞尔曲线

CGPathAddRect   添加一个矩形,一个可变的图形路径。
CGPathAddRects  追加矩形可变图形路径数组。
CGPathAddRoundedRect   添加一个圆角矩形可变图形路径。
CGPathApply   每个元素的图形路径中,调用一个自定义应用功能。
CGPathMoveToPoint   开始在一个可变的图形路径指定一个位置,一个新的子路径。
CGPathCloseSubpath   关闭和一个可变的图形路径完成子路径。
CGPathAddEllipseInRect   添加一个路径,一个适合矩形内的椭圆。

Getting Information about Quartz Paths

CGPathEqualToPath  指示是否两个图形路径是等效的。
CGPathGetBoundingBox  返回包含在图形路径中的所有点的包围盒。
CGPathGetPathBoundingBox   返回图形路径的包围盒
CGPathGetCurrentPoint   返回图形路径中的当前点。
CGPathGetTypeID   返回用于石英图形路径的核心基础类型标识符。
CGPathIsRect     指出是否代表一个矩形图形路径。
CGPathContainsPoint  检查一个点是否包含在图形路径中。
CGLineCap   用于渲染一个行的端点的样式。
CGLineJoin   用于线的连接类型。

苹果官CGPath

CGRectGet系列

CGRectInset(CGRect rect, CGFloat dx, CGFloat dy) dx,dy 是在rect的内部左右,上下距离的值。
CGRectGetHeight返回label本身的高度 
CGRectGetMinY返回label顶部的坐标 
CGRectGetMaxY 返回label底部的坐标
CGRectGetMinX 返回label左边缘的坐标 
CGRectGetMaxX 返回label右边缘的坐标 
CGRectGetMidX表示得到一个frame中心点的X坐标 
CGRectGetMidY表示得到一个frame中心点的Y坐标

根据颜色绘制图片

  -(UIImage *)imageFromColor:(UIColor*)color
  {
    CGRect rect = CGRectMake(0, 0, 1, 1);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context,[color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

值得注意的一点是:

CGContextSaveGState(context);和CGContextRestoreGState(context); 这一对方法的作用是,前者的调用,将会把当前的上下文状态保存在一个“绘图状态栈”中,后者的作用是,将上一次保存在栈中的上下文状态取出,作为当前的上下文状态。这样做的目的,是因为对上下文进行变换会改变上下文整体坐标系,如果在变换上下文前,不进行保存,之后也不恢复的话,再在此上下文绘图,就会按照新的变化后的坐标系绘图,从而发生混乱。

小结

CGContextRefCGMutablePathRef 都是画图工具,但是

  • CGContextRef 可以自己展示出图形
  • CGMutablePathRef 需要与CAShapeLayerCGContextRef配合使用后才可以展示出图形,它只是负责绘制路径path的.

推荐好文章: 打造自己的“美图秀秀” 关于Core Image 看这里


效果.gif

本文考虑到简洁就不上代码了,具体的代码实现的效果可以到我GitHub去下载查看,喜欢的话,请star 一下。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏儿童编程

《动物魔法学校》儿童学编程Scratch之“外观”部分

导读:本文通过一个案例《动物魔法学校》来学习Scratch语言的“外观”部分。之后通过一系列其他功能的综合运用对作品功能进行了扩展。

19240
来自专栏儿童编程

一张图理清《梅花易数》梗概

学《易经》的目的不一定是为了卜卦,但是了解卜卦绝对能够让你更好地了解易学。今天用一张思维导图对《梅花易数》的主要内容进行概括,希望能够给学友们提供帮助。

32340
来自专栏儿童编程

什么样的人生才是有意义的人生——没有标准的标准答案

【导读】其实我们可以跳出这个小圈圈去更加科客观地看一下这个世界。在夜晚的时候我们仰望天空,浩瀚的宇宙中整个地球只是一粒浮尘,何况地球上一个小小的人类?在漫长的历...

1.8K50
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

18230
来自专栏儿童编程

声音功能让儿童编程更有创造性

导读:Scratch中声音功能非常强大,除了常规的音效,你甚至可以模拟各种乐器的各个发音、设置节拍、休止……如果你愿意,甚至可以用它创作一个交响乐。我们可以引导...

13840
来自专栏儿童编程

天干地支五行八卦的对应关系

19790
来自专栏儿童编程

我不是算命先生,却对占卜有了疑惑——如何论证“占卜前提”的正确与否

事出有因,我对《周易》感兴趣了很多年。只是觉得特别有趣,断断续续学习了一些皮毛。这几天又偶然接触到了《梅花易数》,觉得很是精彩,将五行八卦天干地支都串联了起来。...

15310
来自专栏儿童编程

儿童创造力教育与编程教育的碰撞——MIT雷斯尼克教授最新理论梗概

儿童编程教育已经在我国各一线二线城市疯狂出现,颇有“烂大街”的趋势。我们不禁要问很多很多问题:

22370
来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.2K20
来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

29940

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励