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;

你可能感兴趣的:(IOS图形绘制路径 CGPATH & CGCONTEXT相关联的CGPath & UIBezierPath)