zoukankan      html  css  js  c++  java
  • iOS 2D绘图 (Quartz2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)

    博客原地址:http://blog.csdn.net/hello_hwc?viewmode=list

    让我们继续跟着大神的脚步前进吧。这一次 我们学习一些Quartz 2D 最基本的一些用法。

    前言:一个路径可以包含由一个或者多个shape以及子路径subpath,Quartz提供了很多方便的shape可以直接调用。例如:point line Arc(圆弧),Curves(曲线),Ellipse(椭圆), Rectangle(矩形)。

     对这些path可以进行stroke(描边),也可以进行fill(填充),也可以利用path对一个区域进行截取(clip)

    例如 使用截取圆形区域

    绘制 Points / lines

    Quartz 2D中 使用方法 CGContextMoveToPoint移动画笔到一个点来开始一个新的子路径,使用CGContextAddLineToPint来从当前开始点添加一条线到结束点。

    注意:CGContextAddLineToPoint调用后,开始点会重新设置,直到结束点。

    举个例子:

    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
        CGContextRef context = UIGraphicsGetCurrentContext();
        //设置填充颜色
        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        //设置描边颜色
        CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
        
        //为了颜色更好的区分 对矩形进行描边
        CGContextFillRect(context, rect);
        CGContextStrokeRect(context, rect);
        //实际line和point代码
        CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
        //设置画笔的宽度
        CGContextSetLineWidth(context, 4.0);
        //设置线的顶端的样式
        CGContextSetLineCap(context, kCGLineCapRound);
        //设置线相交处的样式
        CGContextSetLineJoin(context, kCGLineJoinRound);
        CGPoint selfCent = CGPointMake(self.bounds.size.width / 2 + 10, self.bounds.size.height / 2);
        CGFloat width = 40;
        //设置画线的起点
        CGContextMoveToPoint(context, selfCent.x - width / 2, selfCent.y - width / 2);
        //移动画笔到结束点,并将结束点作为下一次画线的起点
        CGContextAddLineToPoint(context, selfCent.x - width / 2, selfCent.y + width / 2);
        CGContextAddLineToPoint(context, selfCent.x + width / 2, selfCent.y);
        CGContextAddLineToPoint(context, selfCent.x - width / 2, selfCent.y - width / 2);
        //提交 开始渲染
        CGContextStrokePath(context);
    }

    效果:

    这里 我们提一下线的顶端模式 使用CGContextLineCao来设置

    线的相交模式 使用CGContextLineJoin来设置,一共也有三种

    画虚线

    //画虚线
    - (void)drawDashLineInRect:(CGRect)rect andContext:(CGContextRef)context {
        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
        
        CGContextFillRect(context, rect);
        CGContextStrokeRect(context, rect);
        //设置描边颜色
        CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
        //设置下画笔的宽度
        CGContextSetLineWidth(context, 1.0);
        //设置线的顶端样式
        CGContextSetLineCap(context, kCGLineCapRound);
        //设置相交线的样式
        CGContextSetLineJoin(context, kCGLineJoinRound);
        
        //开始画线
        CGFloat lengths[] = {5,15};
        //参数说明
        /*
         context 这个不用多书
         phase 表示第一个虚线绘制的时候要跳过多少个点
         lengths = {10,10}表示先绘制10个点 跳过十个点 在绘制10个点 如此反复
         如果把lengths值改为{10, 20, 10},则表示先绘制10个点,跳过20个点,绘制10个点,跳过10个点,再绘制20个点,如此反复,如图:
         count 表示lengths数组的长度
         */
        CGContextSetLineDash(context, 1, lengths, 2);
        CGContextMoveToPoint(context,70,50);
        CGContextAddLineToPoint(context, 30, 30);
        CGContextAddLineToPoint(context, 30, 70);
        CGContextAddLineToPoint(context, 70, 50);
        CGContextStrokePath(context);
    }

    效果图:

    参数说明

    void CGContextSetLineDash (
       CGContextRef _Nullable c,
       CGFloat phase,
       const CGFloat * _Nullable lengths,
       size_t count
    );

    c 绘制的context,这个不用多说
    phase,第一个虚线段从哪里开始,例如传入3,则从第三个单位开始 如果lengths = {10,10}则从第三个单位开始 画七个单位 跳过十个单位 在画是个单位 跳过十个单位 以此类推。
    lengths,一个C数组,表示绘制部分和空白部分的分配。例如传入[2,2],则绘制2个单位,然后空白两个单位,以此重复
    count lengths的数量


    画圆弧

    Quartz 2D提供了两个方法来绘制圆弧

    CGContextAddArc:普通的圆弧的一部分(以某个点为圆心,指定半径 和多大弧度的圆弧)

    CGContextAddArcToPoint:用来绘制圆角,下文会详细阐述。

    CGContextAddArc 参数说明:

    void CGContextAddArc (
       CGContextRef _Nullable c,
       CGFloat x,
       CGFloat y,
       CGFloat radius,
       CGFloat startAngle,
       CGFloat endAngle,
       int clockwise
    );

    c,context不用说了 日常传上下文

    x , y 指定坐标原点

    radius 指定半径的长度

    startAngle/endAngle 指定某一段弧度

    clockwise 1 表示顺时针 0 表示逆时针

    代码示例 哈哈哈哈哈

    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
        
    CGContextFillRect(context, rect);
    CGContextStrokeRect(context, rect);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextAddArc(context, 100, 100, 50, 0, M_PI, 1);
    CGContextStrokePath(context);

    效果:

    CGContextAddArcToPoint这个方法比较复杂 但是理解了也没有什么难度

    函数体

    void CGContextAddArcToPoint (
       CGContextRef _Nullable c,
       CGFloat x1,
       CGFloat y1,
       CGFloat x2,
       CGFloat y2,
       CGFloat radius
    );

    参数

    c context 不用说了

    x1,y1和当前点(x0,y0)决定了第一条切线(x0,y0)->(x1,y1)

    x2,y2和(x1,y1)决定了第二条切线

    radius,想切的半径。

    也就是说

    绘制一个半径为radius的圆弧 和上述两条直线都相切。

    代码

    CGContextMoveToPoint(context, 100, 50);
    CGContextAddArcToPoint(context,100,0,50,0, 50);
    CGContextStrokePath(context);

    效果

    解释为什么

    图中的两条红线就是上文提到的两条线,分别是(x0,y0)->(x1,y1)和(x1,y1)->(x2,y2),那么和这两条线都想切的自然就是图中的蓝色圆弧了


    椭圆/矩形

    这两个比较简单 就不再多说了

    - (void)addEllipseAndRectInRect:(CGRect)rect{
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
        
        CGContextFillRect(context, rect);
        CGContextStrokeRect(context, rect);
        //设置画笔的颜色
        CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
        CGContextSetLineWidth(context, 2.0f);
        //画椭圆
        CGContextAddEllipseInRect(context, CGRectMake(10, 10, 100, 70));
        //画矩形
        CGContextAddRect(context, CGRectMake(10, 10, 100, 70));
        //渲染
        CGContextStrokePath(context);
    }

    效果:


    曲线

    Quartz 2D 使用计算机图形学中的多项式绘制曲线 支持二次和三次曲线

    利用函数CGContextAddCurveToPoint可以绘制三次曲线

    函数体

    void CGContextAddCurveToPoint (
       CGContextRef _Nullable c,
       CGFloat cp1x,
       CGFloat cp1y,
       CGFloat cp2x,
       CGFloat cp2y,
       CGFloat x,
       CGFloat y
    );

    参数说明

    c context 不用多说

    cp1/cp2第一个控制点

    cp2/cp2第二个控制点

    x/y 结束点

    具体效果如图

    使用函数CGContextAddQuadCurveToPoint 来绘制二次曲线

    函数体

    void CGContextAddQuadCurveToPoint (
       CGContextRef _Nullable c,
       CGFloat cpx,
       CGFloat cpy,
       CGFloat x,
       CGFloat y
    );

    参数说明

    c context

    cpx/cpy 控制点

    x/y 结束点

    效果

    来个例子看一下

    吼吼哈嘿

    //画曲线
    - (void)addCurveInRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
        
        CGContextFillRect(context, rect);
        CGContextStrokeRect(context, rect);
        //画二次曲线
        //设置起点
        CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
        CGContextMoveToPoint(context, 10, 150);
        CGContextAddQuadCurveToPoint(context, 30, 10, 150, 160);
        CGContextStrokePath(context);
        
        //画三次曲线
        //保存上下文 同时也是结束上次的绘制
        CGContextSaveGState(context);
        CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
        //设置起点
        CGContextMoveToPoint(context, 10, 190);
        CGContextAddCurveToPoint(context, 50, 100, 200, 150, 200, 10);
        CGContextStrokePath(context);
        //提出最新的上下文
        CGContextRestoreGState(context);
        
    }

    效果图

    当曲线和动画结合起来,用处会很大。如果写到动画那一部分 会结合起来讲解。

  • 相关阅读:
    缓冲区溢出实验 6 exit(0)
    缓冲区溢出实验 1 strcpy
    缓冲区溢出实验 5 Snprintf
    [LeetCode] 130. Surrounded Regions 包围区域
    [LeetCode] 547. Friend Circles 朋友圈
    [LeetCode] 200. Number of Islands 岛屿的数量
    [LeetCode 695] Max Area of Island 岛的最大面积
    [LeetCode] 3. Longest Substring Without Repeating Characters 最长无重复字符的子串
    [LeetCode] 5. Longest Palindromic Substring 最长回文子串
    [LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治
  • 原文地址:https://www.cnblogs.com/huanying2000/p/6225724.html
Copyright © 2011-2022 走看看