iOS程序猿之iOS绘图基础(draw)

本文介绍了iOS绘图的基础概念,包括context、path、描边和填充。详细阐述了画图的步骤,并讲解了如何通过重写UIView的drawRect方法获取上下文。还探讨了填充颜色的三种模式以及非零绕数规则和奇偶规则。最后,提供了基础绘图的代码示例,如画线、圆和圆弧的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iOS绘图基础(draw)

先说几个基本概念:
  • context:上下文,ios绘图的方法都需要传一个上下文context,这个context在重写uiview的drawRect的方法里调用UIGraphicsGetCurrentContext()获取
  • path:路径,ios绘图可以想象为你拿着一支笔去画图,画几条线或几个点从而形成一个路径,之后可以利用理解去填色或者描边
  • stroke,fill 描边和填充,每个路径都需要填充或者描边后才能在视图中看见,他们都各自有很多样式可以设置,常见的有颜色、粗细、渐变,连接样式等等。
  • 画图可以使用默认路径画,或者单独创建path画图,对应画图的api并不完全相同,是两组名称相似的api,两组pi常用的方法如下

CGContextMoveToPoint设置起点
CGContextClosePath 连接起点和当前点
CGPathCreateMutable 类似于 CGContextBeginPath
CGPathMoveToPoint 类似于 CGContextMoveToPoint
CGPathAddLineToPoint 类似于 CGContextAddLineToPoint
CGPathAddCurveToPoint 类似于 CGContextAddCurveToPoint
CGPathAddEllipseInRect 类似于 CGContextAddEllipseInRect
CGPathAddArc 类似于 CGContextAddArc
CGPathAddRect 类似于 CGContextAddRect
CGPathCloseSubpath 类似于 CGContextClosePath
CGContextAddPath函数把一个路径添加到graphics

画图步骤

1:获取context,

2:设置路径

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

3:填充或描边路径

关于填充颜色 填充颜色有3种模式,分别是1:填充笔触,就是只给路径描边,2:根据路径填充颜色 3:填充笔触和颜色。填充颜色也分为非零绕数规则和奇偶规则,这个概念比较复杂难以解释,大家可以百度看看或者花几个图试试就明白。

几种基础绘图的代码

1.准备工作

新建一个继承于UIView的类, 重写-(void)drawRect:(CGRect)rect; 方法

// 重写drawRect
- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    // 1.获取上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    /**********2.设置画图相关样式参数*********/
    
    // 设置笔触的颜色
    CGContextSetStrokeColorWithColor(contextRef, [UIColor blueColor].CGColor); // 设置颜色有很多方法,推荐这个
    
    // 设置笔触的宽度
    CGContextSetLineWidth(contextRef, 2);
    
    // 设置填充色
    CGContextSetFillColorWithColor(contextRef, [UIColor purpleColor].CGColor);
    
    // 设置拐点样式
    /**
     *  enum CGLineJoin {
     *      kCGLineJoinMiter, //尖的,斜接
     *      kCGLineJoinRound, //圆
     *      kCGLineJoinBevel //斜面
     *  }
     */
    CGContextSetLineJoin(contextRef, kCGLineJoinRound);
    
    // 设置线两端的样式
    /**
     *  enum CGLineCap {
     *      kCGLineCapButt,
     *      kCGLineCapRound,
     *      kCGLineCapSquare
     *  };
     */
    CGContextSetLineCap(contextRef, kCGLineCapRound);
    
    // 设置虚线线条的样式
//    CGFloat lengths[] = {10, 10};
//    CGContextSetLineDash(contextRef, 0, lengths, 2);
    
    /**********设置画图相关样式参数*********/

    /**********3.开始画图*********/

    // 画线
    [self drawline:contextRef];
    
    // 画圆,圆弧,贝塞尔曲线
    [self drawCircle:contextRef];
    
    // 画矩形,画椭圆,多边形
    [self drawShape:contextRef];
    
    // 画文字
    [self drawText:contextRef];
    
    // 画图片
    [self drawPicture:contextRef];
    
    /**********结束画图*********/

}

2.画线

第一个方法我写的比较详细,写了使用path的方式和直接画线的方式。推荐使用path的方式画线。 另外,第一个方法也写了移动笔触画线和用点集合画线。后面方法只会涉及其中一种,因为方法都比较类似。

- (void)drawline:(CGContextRef)contextRef
{
    // 画一条简单的线
    CGPoint points1[] = {CGPointMake(10, 30), CGPointMake(300, 30)};
    CGContextAddLines(contextRef, points1, 2);
    
    
    // 画线方法1, 使用CGContextAddLineToPoint添加点画线,需要先设置一个起始点
    // 设置起始点
    CGContextMoveToPoint(contextRef, 50, 50);
    // 添加一个点
    CGContextAddLineToPoint(contextRef, 100, 50);
    // 在添加一个点,变成折现
    CGContextAddLineToPoint(contextRef, 150, 100);
    // 在添加一个点,再折一下
    CGContextAddLineToPoint(contextRef, 280, 100);
    
    
    // 画线方法2
    // 构造线路的点数组
    CGPoint points2[] = {CGPointMake(50, 120), CGPointMake(100, 150), CGPointMake(150, 120), CGPointMake(200, 150), CGPointMake(250, 120)};
    CGContextAddLines(contextRef, points2, 5); // 最后一个参数为要绘制点的个数
    
    
    // 画线方法3
    // 利用路径去画一组点(推荐使用路径的方式,虽然多了几行代码,带上逻辑更加清晰了)
    // 路径1
    CGMutablePathRef path1 = CGPathCreateMutable();
    CGPathMoveToPoint(path1, &CGAffineTransformIdentity, 30, 180); // 起始点, CGAffineTransformIdentity 类似于初始化一些参数
    CGPathAddLineToPoint(path1, &CGAffineTransformIdentity, 30, 220); // 添加一个点
    CGPathAddLineToPoint(path1, &CGAffineTransformIdentity, 80, 220); // 添加一个点
    // 将路径1加入contextRef
    CGContextAddPath(contextRef, path1);
    // path同样有方法CGPathAddLines()添加一组路径,和CGContextAddLines()差不多
    
    /******** 上面的方法都要写下面这两句代码 ********/
    // 描出笔触
    CGContextStrokePath(contextRef);
    // 填充
    CGContextFillPath(contextRef);
}

3. 画圆,圆弧,贝塞尔曲线

画圆和圆弧是一回事,只是起点和重点位置不同,画圆画弧线主要依赖于这几个方法CGContextAddArc,CGContextAddArcToPoint,CGContextAddCurveToPoint,CGContextAddQuadCurveToPoint后面两个方法是贝塞尔二次曲线和三次曲线

- (void)drawCircle:(CGContextRef)contextRef
{
    // 画笔改成紫色,便于区别
    CGContextSetStrokeColorWithColor(contextRef, [UIColor greenColor].CGColor);
    
    /** 绘制路径 方法一
     *  void CGContextAddArc (
     *      CGContextRef c,
     *      CGFloat x,             //圆心的x坐标
     *      CGFloat y,    //圆心的x坐标
     *      CGFloat radius,   //圆的半径
     *      CGFloat startAngle,    //开始弧度
     *      CGFloat endAngle,   //结束弧度
     *      int clockwise          //0表示顺时针,1表示逆时针
     *  );
     */
    
    // 圆
    CGContextAddArc(contextRef, 100, 100, 50, 0, M_PI*2, 0);
    CGContextStrokePath(contextRef);
    
    // 半圆
    CGContextAddArc(contextRef, 100, 200, 50, M_PI, M_PI*2, 0);
    CGContextStrokePath(contextRef);
    
    /**
     *  绘制路径 方法二,这个方法适合绘制弧度,端点p1和p2是弧线的控制点,类似photoshop中的钢笔工具控制曲线,还不明白请去了解贝塞尔曲线
     *  void CGContextAddArcToPoint(
     *      CGContextRef c,
     *      CGFloat x1,  //端点1的x坐标
     *      CGFloat y1,  //端点1的y坐标
     *      CGFloat x2,  //端点2的x坐标
     *      CGFloat y2,  //端点2的y坐标
     *      CGFloat radius //半径
     *  )
     */
    
    
    // 1/4 弧度*4 划出一个圆形
    CGContextMoveToPoint(contextRef, 100, 100);
    CGContextAddArcToPoint(contextRef, 100, 50, 150, 50, 50);
    CGContextAddArcToPoint(contextRef, 200, 50, 200, 100, 50);
    CGContextAddArcToPoint(contextRef, 200, 150, 150, 150, 50);
    CGContextAddArcToPoint(contextRef, 100, 150, 100, 100, 50);
    CGContextStrokePath(contextRef);
    
    
    // 贝塞尔曲线
    CGContextSetStrokeColorWithColor(contextRef, [UIColor orangeColor].CGColor); // 画笔颜色
    /** 三次曲线函数
     *  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坐标
     *  );
     */
    
    CGContextMoveToPoint(contextRef, 100, 300);
    CGContextAddCurveToPoint(contextRef, 100, 300, 200, 0, 200, 300);
    CGContextStrokePath(contextRef);
    
    //三次曲线可以画圆弧
    CGContextMoveToPoint(contextRef, 200, 200);
    CGContextAddCurveToPoint(contextRef, 200, 100, 300, 100, 300 ,100);
    CGContextStrokePath(contextRef);
    
    /** 二次曲线
     *  void CGContextAddQuadCurveToPoint (
     *  CGContextRef c,
     *  CGFloat cpx,  //控制点 x坐标
     *  CGFloat cpy,  //控制点 y坐标
     *  CGFloat x,  //直线的终点 x坐标
     *  CGFloat y  //直线的终点 y坐标
     *  );
     */
    
    CGContextMoveToPoint(contextRef, 100, 100);
    CGContextAddQuadCurveToPoint(contextRef, 200, 0, 300, 150);
    CGContextStrokePath(contextRef);
}

4.画矩形,画椭圆,多边形

- (void)drawShape:(CGContextRef)contextRef
{
    CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor);
    
    // 画椭圆,如果长宽相等就是圆
    CGContextAddEllipseInRect(contextRef, CGRectMake(50, 250, 50, 100));
    
    // 画矩形,长宽相等就是正方形
    CGContextAddRect(contextRef, CGRectMake(150, 250, 50, 100));
    
    // 画多边形,多边形是通过path完成的
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, &CGAffineTransformIdentity, 50, 350);
    CGPathAddLineToPoint(path, &CGAffineTransformIdentity, 100, 350);
    CGPathAddLineToPoint(path, &CGAffineTransformIdentity, 80, 400);
    CGPathCloseSubpath(path);
    CGContextAddPath(contextRef, path);
    
    
    // 填充
    CGContextFillPath(contextRef);
}

5. 画文字

- (void)drawText:(CGContextRef)contextRef
{
    // 文字样式
    UIFont *font = [UIFont systemFontOfSize:18];
    NSDictionary *dict = @{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor colorWithRed:0.167 green:0.752 blue:1.000 alpha:1.000]};
    [@"荣耀归来" drawInRect:CGRectMake(100, 450, 100, 50) withAttributes:dict];
}

6.画图片

// 画图片
- (void)drawPicture:(CGContextRef)contextRef
{
    UIImage *image = [UIImage imageNamed:@"17.png"];
    [image drawInRect:CGRectMake(100, 500, 100, 150)]; // 在坐标系中画出图片
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值