iOS CGContextRef&CGMutablePathRef&UIBezierPath简单学习

简单的四句介绍

Quartz是一个二维绘图引擎,使用的是CoreGraphics库,同时支持iOS和Mac系统

CGContextRef:获取图形上下文.或者叫作用域,即画布,他是专门用来保存绘画期间的各种数据的

UIBezierPath是对CGPathRef的封装。创建矢量图形时,拆解成一条或者多条线段,拼接起来,每条下端的终点都是下一条线段的起点

当我们绘制路径时,Path的信息就会被Graphics context重置。 如果我们想要保存path信息,并多次使用它,我们就可以用到CGPathCreatMutable申请路径,然后用CGPathAddLintToPoint等方法来添加路径。

1.设置点和线

介绍属性
  • 先设置一个起点
  • 添加一个中间点
  • 画一个矩形
  • 画一个圆形
  • 画一个扇形
  • 二阶曲线
  • 三阶曲线
CGContextRef UIBezierPath CGMutablePathRef
CGContextMoveToPoint moveToPoint CGPathMoveToPoint
CGContextAddLineToPoint addLineToPoint CGPathAddRect
CGContextAddRect bezierPathWithRect CGPathAddRect
CGContextAddEllipseInRect bezierPathWithOvalInRect CGPathAddEllipseInRect
CGContextAddArc addArcWithCenter CGPathAddArcToPoint
CGContextAddQuadCurveToPoint addQuadCurveToPoint CGPathAddQuadCurveToPoint
CGContextAddCurveToPoint addCurveToPoint CGPathAddCurveToPoint

2、设置线的属性

这些设置线属性的API都是通用的

  • 线宽 CGContextSetLineWidth
  • 线的颜色 CGContextSetStrokeColorWithColor
  • 填充颜色 CGContextSetFillColorWithColor
  • line join CGContextSetLineCap
  • line cap CGContextSetLineJoin
  • 透明度 CGContextSetAlpha
  • 设置阴影 CGContextSetShadow
  • 设置阴影颜色 CGContextSetShadowWithColor
  • 切割操作 CGContextClip

思维导图

基础绘图.png

CGContextRef介绍

需要代码的请参考这里

52C4C92C-D5C3-45A2-A05A-B25943165601.png
Quartz2d是一个二维绘图引擎,使用的是CoreGraphics库,同时支持iOS和Mac系统

有点难,比较底层,操作系统层api一般都是纯C开发的,有针对性的开发才会用到

要基于UIView去开发

实战用途

画线段
  • 画直线CGContextAddLineToPoint

  • 画虚线CGContextSetLineDash

画三角形

  • CGContextClosePath
画矩形
  • CGContextAddRect
画圆
  • CGContextAddEllipseInRect
画扇形
  • CGContextAddArc
画曲线
  • CGContextAddQuadCurveToPoint

  • CGContextAddCurveToPoint

画特效
  • CGContextSetShadow

  • CGContextSetAlpha

绘制文字
  • drawInRect
绘制图片
  • drawInRect

  • CGContextClip

变换运用(改变画布位置)
  • CGContextTranslateCTM

  • CGContextRotateCTM

  • CGContextScaleCTM

1、CGContextRef之画线段

CGContextRef 具有贯穿全局的效果,我们设置一个全局变量创建 一次 就可以了

虚线
- (void)drawLine1{
    //获取图形上下文.或者叫作用域,即画布,他是专门用来保存绘画期间的各种数据的
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    //路径设置
    //先设置一个起点
    CGContextMoveToPoint(contextRef, 50, 100);
    //设置终点
    CGContextAddLineToPoint(contextRef, 100, 500);
    
    //设置样式
    //设置线宽
    CGContextSetLineWidth(contextRef, 5.0f);
    //设置线的颜色
    CGContextSetStrokeColorWithColor(contextRef, [UIColor redColor].CGColor);
    
    //风格  头部和尾部的处理
    CGContextSetLineCap(contextRef, kCGLineCapRound);
    
    
    /*
     画虚线
     参数1 作用域
     参数2 起点的偏移量
     参数3 指明虚线是如何交替绘制
     lengths的值{10,10}表示先绘制10个点,再跳过10个点
     如果把lengths值改为{10, 20, 10},则表示先绘制10个点,跳过20个点,绘制10个点,跳过10个点,再绘制20个点,
     参数4 实心部分和虚心部分的循环次数
     */
    CGFloat lenths[] = {10, 10};
    CGContextSetLineDash(contextRef, 0, lenths, 2);
    
    
    //渲染
    CGContextStrokePath(contextRef);
}

效果图

屏幕快照 2017-07-14 上午10.17.30.png
2、CGContextRef之画多边形
画三角形
- (void)drawTriangle{
    //获取图形上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    //设置点
    CGContextMoveToPoint(contextRef, 100, 100);
    CGContextAddLineToPoint(contextRef, 200, 200);
    CGContextAddLineToPoint(contextRef, 100, 200);
    
    //把点封闭起来
    CGContextClosePath(contextRef);
    
    //设置线宽
    CGContextSetLineWidth(contextRef, 3.0f);
    //设置线的颜色
    CGContextSetStrokeColorWithColor(contextRef, [UIColor redColor].CGColor);
    //设置填充颜色
    CGContextSetFillColorWithColor(contextRef, [UIColor greenColor].CGColor);
    
    
    // 如果写了多种渲染方式,那么只执行第一种
//    CGContextStrokePath(contextRef);
//    CGContextFillPath(contextRef);
    
    CGContextDrawPath(contextRef, kCGPathFillStroke);
 
}

效果图


屏幕快照 2017-07-14 上午10.19.41.png
画正方形
//获取图形上下文
   CGContextRef contextRef = UIGraphicsGetCurrentContext();
   
   CGContextAddRect(contextRef, CGRectMake(100, 100, 100, 100));
   
   //颜色的填充
   CGContextSetFillColorWithColor(contextRef, [UIColor redColor].CGColor);
   //线宽
   CGContextSetLineWidth(contextRef, 4.0f);
   CGContextSetStrokeColorWithColor(contextRef, [UIColor blueColor].CGColor);
   
   //渲染
   CGContextDrawPath(contextRef, kCGPathFillStroke);

效果图


屏幕快照 2017-07-14 上午10.20.33.png
3、CGContextRef之画曲线
画圆
  // 绘制图形上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    CGContextAddEllipseInRect(contextRef, CGRectMake(100, 100, 100, 100));
    
    CGContextDrawPath(contextRef, kCGPathFillStroke);

扇形
- (void)drawArc1{
    
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    /*
     参数1:作用域
     参数2:圆心x坐标
     参数3:圆心y坐标
     参数4:半径
     参数5:开始角度
     参数6:结束角度
     参数7:方向,0表示顺时针,1表示逆时针
     
     */
    CGContextAddArc(contextRef, 100, 200, 100, 0, M_PI_4, 0);
    
    CGContextSetLineWidth(contextRef, 5.0f);
    CGContextSetFillColorWithColor(contextRef, [UIColor greenColor].CGColor);
    CGContextSetStrokeColorWithColor(contextRef, [UIColor redColor].CGColor);
    
    
//    CGContextAddLineToPoint(contextRef, 100, 200);
    
    CGContextDrawPath(contextRef, kCGPathFillStroke);
    
    
}




- (void)drawArc2{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    
    //第一部分
    CGContextMoveToPoint(contextRef, 250, 400);
    CGContextAddArc(contextRef, 250, 400, 100, 0, M_PI_2, 0);
    CGContextSetFillColorWithColor(contextRef, [UIColor blueColor].CGColor);
    CGContextFillPath(contextRef);
    
    
    //第二部分
    CGContextMoveToPoint(contextRef, 250, 400);
    CGContextAddArc(contextRef, 250, 400, 100, M_PI_2, M_PI_2/2*3, 0);
    CGContextSetFillColorWithColor(contextRef, [UIColor redColor].CGColor);
    CGContextFillPath(contextRef);
    
    // 第三部分
    CGContextMoveToPoint(contextRef, 250, 400);
    CGContextAddArc(contextRef, 250, 400, 100, 0, 225*M_PI/180.0, 1);
    CGContextSetFillColorWithColor(contextRef, [UIColor purpleColor].CGColor);
    CGContextFillPath(contextRef);

    
}

效果图


屏幕快照 2017-07-14 上午10.22.57.png
画曲线
   
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    //起点
    CGContextMoveToPoint(contextRef, 20, 300);
    /*
     三阶贝塞尔曲线
     参数1:作用域
     参数2:控制点x
     参数3:控制点y
     参数4:控制点x
     参数5:控制点y
     参数6:终点x
     参数7:终点y
     
     - `CGContextAddQuadCurveToPoint`  二阶贝塞尔曲线
     */
    CGContextAddCurveToPoint(contextRef, 100, -100, 200, 900, 300, 400);
     CGContextStrokePath(contextRef);    

效果图

屏幕快照 2017-07-14 上午10.24.32.png
4、CGContextRef之画特效
 CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    
    CGContextAddRect(contextRef, CGRectMake(100, 100, 100, 100));
    CGContextSetFillColorWithColor(contextRef, [UIColor redColor].CGColor);
    CGContextSetStrokeColorWithColor(contextRef, [UIColor greenColor].CGColor);
    CGContextSetLineWidth(contextRef, 5.0f);
    
    //设置透明度
    //取值范围(0~1,0表示全透明,1是不透明)
     CGContextSetAlpha(contextRef, 1);
    
    /*
     设置阴影
     参数1:画布
     参数2:右偏移量
     参数3:下偏移量
     参数4:模糊度(0是不模糊,越大越模糊,10就差不多)
     */
    CGContextSetShadow(contextRef, CGSizeMake(10, 10), 10);
    
    
    CGContextDrawPath(contextRef, kCGPathFillStroke);

效果图


屏幕快照 2017-07-14 上午10.25.44.png
5、CGContextRef之绘制
绘制文字
 NSDictionary *dic = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:15],
                           NSForegroundColorAttributeName : [UIColor redColor]
                          };
    // 两种的区别drawInRect会自动换行,drawAtPoint:CGPointZero不会自动换行
    [text drawInRect:CGRectMake(20, 100, self.bounds.size.width - 40, 100) withAttributes:dic];
//    [text drawAtPoint:CGPointMake(20, 200) withAttributes:dic];
绘制图片
- (void)drawImage{
    UIImage *image = [UIImage imageNamed:@"image.jpg"];
    [image drawInRect:CGRectMake(100, 100, 250, 250)];
    // 平铺图像,超出部分会自动剪裁
//    [image drawAsPatternInRect:self.bounds];
    // 如果实现文字和图片共存,需要将文字写在后面,防止被图片盖住
    NSDictionary *dic = @{
                          NSFontAttributeName:[UIFont systemFontOfSize:15],
                          NSForegroundColorAttributeName : [UIColor redColor]
                          };
    NSString *text = @"如果实现文字和图片共存,需要将文字写在后面,防止被图片盖住";
    [text drawInRect:CGRectMake(100, 300, 250, 100) withAttributes:dic];
}

-(void)clipImage{
    /*
     思路:先画一个圆,让图片显示在圆的内部,超出的部分不显示。
     注意:显示的范围只限于指定的剪切范围,无论往上下文中绘制什么东西,只要超出了这个范围的都不会显示。
     */
    
    
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    // 先画一个圆形
    CGContextAddEllipseInRect(contextRef, CGRectMake(100, 400, 200, 200));
    
    // 切割操作
    CGContextClip(contextRef);
    CGContextFillPath(contextRef);
    
    
    UIImage *image = [UIImage imageNamed:@"image.jpg"];
    [image drawInRect:CGRectMake(100, 400, 200, 200)];
    

}


效果图


屏幕快照 2017-07-14 上午10.28.28.png
5、CGContextRef之图形变换
 
    UIImage *image0 = [UIImage imageNamed:@"image.jpg"];
    [image0 drawInRect:CGRectMake(300, 400, 100, 100)];
    
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    // 移动变换
    //    CGContextTranslateCTM(contextRef, -100, -100);
    /**
     *  对象沿着x轴移动-100单位,沿着y轴移动-100单位
     */
    // 多个变换会叠加
    // 缩放
    //    CGContextScaleCTM(contextRef, 0.5, 0.5);
    
    // 获取中心点
//    CGFloat cenX = CGRectGetMidX(self.bounds);
//    CGFloat cenY = CGRectGetMidY(self.bounds);
//    
    
    // 先移动一下
    //    CGContextTranslateCTM(contextRef, cenX, cenY);
    CGContextTranslateCTM(contextRef, 100+100/2.0, 100+100/2.0);
    
    // 旋转变换
    CGContextRotateCTM(contextRef, M_PI_4);
    // 再移动回去
    CGContextTranslateCTM(contextRef, -(100+100/2.0), -(100+100/2.0));
    
    /**
     *  旋转可以认为实质是旋转坐标系,会绕着坐标原点旋转,可以先将坐标原点移动到要旋转的图形的中点,然后执行旋转,然后再移动回来,实现绕着图形中心旋转的目的
     */
    
    
    UIImage *image = [UIImage imageNamed:@"image.jpg"];
    [image drawInRect:CGRectMake(300, 400, 100, 100)];
    

效果图

屏幕快照 2017-07-14 上午10.29.55.png

UIBezierPath

使用步骤

  • 创建一个 UIBezierPath 对象

  • 用 moveToPoint: 设置初始线段的起点

  • 添加线段,定义一或多个子路径

  • 修改 UIBezierPath 的绘图相关的属性,比如stroke path的属性 lineWidth 和 lineJoinStyle , filled path的属性 usesEvenOddFillRule

常用API
  • 创建矩形bezierPathWithRect

  • 创建矩形内切圆bezierPathWithOvalInRect

  • 圆角矩形bezierPathWithRoundedRect

  • 创建弧形bezierPathWithArcCenter

  • 添加直线addLineToPoint

  • 添加弧形线段addArcWithCenter

  • 添加二阶贝塞尔曲线addQuadCurveToPoint

  • 添加三阶贝塞尔曲线addCurveToPoint

代码就不都贴出来了,想要了解的可以点击这里下载源文件。最近会一直研究一些动画方面的知识,想要和我一同学习的,可以点击关注
EB6A7927-0FDA-4C47-AAEF-5C6B41C98C0F.png

参考链接
Quartz 2D学习(一)简单绘制图形
iOS的UIBezierPath类和贝塞尔曲线

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容