IOS图形绘制路径 CGPATH & CGCONTEXT相关联的CGPath & UIBezierPath

独立CGPath总结

CGPathCreateMutable //创建一个可变图形的路径 需要自己释放
CGPathCreateWithEllipseInRect //创建一个椭圆形的不可改变的路径
CGPathCreateWithRect //创建一个不变的矩形路径
CGPathCreateCopy //创建一个不可变的可以拷贝的路径
CGPathCreateCopyByDashingPath //创建一个虚线路径可以复制的
CGPathCreateCopyByStrokingPath //创建一个画的路径
CGPathCreateMutableCopy //创建一个现有的图形路径的副本
 //由一个转换矩阵变换一个图形路径创建一个不可变的副本
CGPathCreateCopyByTransformingPath
//创建一个由一个转换矩阵变换一个图形路径的可变副本
CGPathCreateMutableCopyByTransformingPath


CGPathRelease //递减保留的图形路径计数
CGPathRetain //增加保留的图形路径计数

CGPathAddArc 一个//弧形追加一个可变图形的路径, 可能由直线段之前
CGPathAddEllipseInRect //添加一个适合的椭圆在矩形的内部
CGPathEqualToPath //两个图形路径是否相等
CGPathGetBoundingBox //返回图形路径中包含所有点的包围盒
CGPathGetPathBoundingBox //返回图形路径的边界框
CGPathGetCurrentPoint //返回当前点的路径
CGPathGetTypeID //返回Quartz图形路径的核心基础类型的标识符

CGPathIsEmpty //指示路径是否为空
CGPathIsRect //图形路径指示是否代表一个矩形
CGPathContainsPoint //检查一个点是否在图形路径中

与CGContext关联的Path总结

点&线

注意

  1. AddLineToPoint实现方式在线条alpha为1,即不透明的时候和AddLines一样,而且是实时画线。
  2. 但是当线条半透明的时候,AddLines在一条线自身重叠时不会透明度重叠。
  3. 而AddLineToPoint却会导致透明度重叠,且move touch的点出也会出现透明度重叠,会显示成点和点之间透明度正确,点上不透明的问题。
//获取上下文
CGContextRef context = UIGraphicsGetCurrentContext();
    //点(在Context中移动画笔到(0,0)个点)
CGContextMoveToPoint(context, 0, 0);
    
    //线(画笔从上一个点画到(1,1)这个点)
CGContextAddLineToPoint(context, 1, 1);
   
    //添加点的坐标
    CGPoint points[] = {
        CGPointMake(0, 0),
        CGPointMake(2, 2),
        CGPointMake(3, 3)
    };
int count = sizeof(points)/sizeof(points[0]);//求出poins长度
CGContextAddLines(context, points, count);//画线
    /*注意
    AddLineToPoint实现方式在线条alpha为1,即不透明的时候和AddLines一样,而且是实时画线。
     但是当线条半透明的时候,AddLines在一条线自身重叠时不会透明度重叠。
     而AddLineToPoint却会导致透明度重叠,且move touch的点出也会出现透明度重叠,会显示成点和点之间透明度正确,点上不透明的问题。
     */

曲线

一种
void CGContextAddArc (
  CGContextRef c,    
  CGFloat x,             //圆心的x坐标
  CGFloat y,  //圆心的x坐标
  CGFloat radius,  //圆的半径
  CGFloat startAngle,    //开始弧度
  CGFloat endAngle,  //结束弧度
  int clockwise          //0表示顺时针,1表示逆时针
);
假如想创建一个完整的圆圈,那么 开始弧度就是0 结束弧度是 2pi, 因为圆周长是 2*pi*r.
最后,函数执行完后,current point就被重置为(x,y).
还有一点要注意的是,假如当前path已经存在一个subpath,那么这个函数执行的另外一个效果是
会有一条直线,从current point到弧的起点
 
第二种
void CGContextAddArcToPoint (
  CGContextRef c,
  CGFloat x1, //端点1的x坐标
  CGFloat y1, //端点1的y坐标
  CGFloat x2, //端点2的x坐标
  CGFloat y2, //端点2的y坐标
  CGFloat radius //半径
);
原理:首先画两条线,这两条线分别是 current point to (x1,y1) 和(x1,y1) to (x2,y2).
这样就是出现一个以(x1,y1)为顶点的两条射线,
然后定义半径长度,这个半径是垂直于两条射线的,这样就能决定一个圆了,更好的理解看下图,不过个人认为下图所标的 tangent point 1的位置是错误的。
最后,函数执行完后,current point就被重置为(x2,y2).
还有一点要注意的是,假如当前path已经存在一个subpath,那么这个函数执行的另外一个效果是
会有一条直线,从current point到(x1,y1)
Paths - happy dog - 又一个部落格

传说中的不规则的曲线

画曲线,一般是一条直线,然后定义几个控制点,使直线变弯曲。
三次曲线函数
void CGContextAddCurveToPoint (
  CGContextRef c,
  CGFloat cp1x, //控制点1 x坐标
  CGFloat cp1y, //控制点1 y坐标
  CGFloat cp2x, //控制点2 x坐标
  CGFloat cp2y, //控制点2 y坐标
  CGFloat x, //直线的终点 x坐标
  CGFloat y //直线的终点 y坐标
);
假如第二个控制点(cp2x,cp2y)比(cp1x,cp1y) 更接近current point,那么会形成一个封闭的曲线
Paths - happy dog - 又一个部落格
 
二次曲线函数
void CGContextAddQuadCurveToPoint (
  CGContextRef c,
  CGFloat cpx, //控制点 x坐标
  CGFloat cpy, //控制点 y坐标
  CGFloat x, //直线的终点 x坐标
  CGFloat y //直线的终点 y坐标
);

裁剪的方法:

CGConextClip;
CGContextEOClip;
CGContextClipToRect;
CGContextClipToRects;
CGContextClipToMask;

图像绘制

UIGraphicsBeginImageContextWithOptions
UIGraphicsEndImageContext

PDF绘制

UIGraphicsBeginPDFContextToFile(ToData)
UIGraphicsEndPDFContext

翻转屏幕变换:

CGContextTranslateCTM(graphicsContext, 0.0, drawingRect.size.height);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);

** CGPATH &CGCONTEXT相关联的CGPath中的对应关系**

CGPathCreateMutable = CGContextBeginPath//创建一个路径
CGPathMoveToPoint = CGContextMoveToPoint//画笔(路径)从哪里开始
CGPathAddLineToPoint = CGContextAddLineToPoint//添加一个点(线)
CGPathAddCurveToPoint = CGContextAddCurveToPoint//创建一个曲线
CGPathAddEllipseInRect = CGContextAddEllipseInRect//创建一个椭圆
CGPathAddArc = CGContextAddArc//创建一个圆形路径
CGPathAddRect = CGContextAddRect//创建一个矩形路径
CGPathCloseSubPath = CGContextCloseSubPath//闭合路径

UIBezierPath

好了看完了上面的各种函数是不是头都大了那么看看我们的UIBezierPath

属性

CGPath:将UIBezierPath类转换成CGPath,类似于UIColor的CGColor

empty:只读类型,路径上是否有有效的元素

bounds:和view的bounds是不一样的,它获取path的X坐标、Y坐标、宽度,但是高度为0

currentPoint:当前path的位置,可以理解为path的终点

lineWidth:path宽度

lineCapStyle:path端点样式,有3种样式
      kCGLineCapButt:无端点
      kCGLineCapRound:圆形端点
      kCGLineCapSquare:方形端点(样式上和kCGLineCapButt是一样的,但是比kCGLineCapButt长一点)

lineJoinStyle:拐角样式
      kCGLineJoinMiter:尖角
      kCGLineJoinRound:圆角
      kCGLineJoinBevel:缺角

miterLimit:最大斜接长度(只有在使用kCGLineJoinMiter是才有效), 边角的角度越小,斜接长度就会越大
为了避免斜接长度过长,使用lineLimit属性限制,如果斜接长度超过miterLimit,边角就会以KCALineJoinBevel类型来显示

flatness:弯曲路径的渲染精度,默认为0.6,越小精度越高,相应的更加消耗性能。

usesEvenOddFillRule:单双数圈规则是否用于绘制路径,默认是NO

UIRectCorner:角
  UIRectCornerTopLeft:左上角
  UIRectCornerTopRight:右上角
  UIRectCornerBottomLeft:左下角
  UIRectCornerBottomRight:右下角
  UIRectCornerAllCorners:所有四个角

UIBezierPath
1.创建UIBezierPath

//矩形路径(rect矩形的位置和大小)
-(instancetype)bezierPathWithRect:(CGRect)rect:

//创建在rect里的内切曲线: (参数:rect-矩形的Frame)
+(instancetype)bezierPathWithOvalInRect:(CGRect)rect:

//创建带有圆角的矩形,当矩形变成正圆的时候,Radius就不再起作用:
//rect:矩形的Frame  cornerRadius:圆角大小)
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius

//圆角的矩形(设定特定的角为)
/*
rect:矩形的Frame
corners:指定的圆角     
cornerRadii:圆角的大小
*/
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
                        byRoundingCorners:(UIRectCorner)corners
                              cornerRadii:(CGSize)cornerRadii;

//圆弧
/*
center->圆点
radius->半径
startAngle->起始位置
endAngle->结束为止
clockwise->是否顺时针方向
*/

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
                                 radius:(CGFloat)radius
                             startAngle:(CGFloat)startAngle
                               endAngle:(CGFloat)endAngle
                              clockwise:(BOOL)clockwise;

//通过已有路径创建路径:
//CGPath->已有路径
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath

一些对象方法

-(void)moveToPoint:(CGPoint)point; //移动到某一点:(point:目标位置)
-(void)addLineToPoint:(CGPoint)point; //绘制一条线:(point:目标位置)
- (void)closePath;//闭合路径,即在终点和起点连一根线
-(void)appendPath:(UIBezierPath *)bezierPath;//追加路径
-(UIBezierPath *)bezierPathByReversingPath;//扭转路径,即起点变成终点,终点变成起点
-(void)applyTransform:(CGAffineTransform)transform;//路径进行仿射变换
-(void)fill; //填充;
-(void)stroke; //描边,路径创建需要描边才能显示出来;
-(void)setStroke;//设置描边颜色,需要在设置后调用描边方法:
-(void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; //设置描边的混合模式

//设置描边的混合模式
//blendMode->混合模式 alpha->透明度
-(void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;

//设置填充的混合模式:
//blendMode:混合模式  alpha:透明度
-(void)strokeWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;

//修改当前图形上下文的绘图区域可见,随后的绘图操作导致呈现内容只有发生在指定路径的填充区域
-(void)addClip;


/**
 *  创建虚线
 *  @param pattern C类型线性数据
 *  @param count   pattern中数据个数
 *  @param phase   起始位置
 */
- (void)setLineDash:(nullable const CGFloat *)pattern
              count:(NSInteger)count
              phase:(CGFloat)phase;




//清空路径:
-(void)removeAllPoints;

/**
 *  创建三次贝塞尔曲线
 *  @param endPoint      终点
 *  @param controlPoint1 控制点1
 *  @param controlPoint2 控制点2
 */
-(void)addCurveToPoint:(CGPoint)endPoint
         controlPoint1:(CGPoint)controlPoint1
         controlPoint2:(CGPoint)controlPoint2;


/**
 *  创建二次贝塞尔曲线
 *  @param endPoint     终点
 *  @param controlPoint 控制点
 */
-(void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;


/**
 *  创建圆弧
 *  @param center     圆点
 *  @param radius     半径
 *  @param startAngle 起始位置
 *  @param endAngle   结束为止
 *  @param clockwise  是否顺时针方向
 */
- (void)addArcWithCenter:(CGPoint)center
                  radius:(CGFloat)radius
              startAngle:(CGFloat)startAngle
                endAngle:(CGFloat)endAngle
               clockwise:(BOOL)clockwise;

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

推荐阅读更多精彩内容