• ios开发日记 10- CGPathAddArc和CGPathAddArcToPoint函数


    http://www.cnblogs.com/mgen/p/3426303.html

    注意:CGPathAddArc和CGContextAddArc,以及UIBezierPath类型的addArcWithCenter:radius:startAngle:endAngle:clockwise:方法原理都类似。而CGPathAddArcToPoint和CGContextAddArcToPoint函数则原理类似。只不过CGPath相关的函数多了一个CGAffineTransform参数,可以直接应用Transform,对于CGContextAddArc和CGContextAddArcToPoint函数,Transform可以使用CGContextXxxCTM方法,之前也写过一篇文章:iOS Quartz: 使用CGContextRef中的Transform来辅助作图

    切入正题,我们首先来看CGPathAddArc函数,我认为CGPathAddArc函数比CGPathAddArcToPoint函数更好理解。可以参考这个SO回答的截图。CGPathAddArc函数是通过圆心和半径定义一个圆,然后通过两个弧度确定一个弧线。注意弧度是以当前坐标环境的X轴开始的。

    需要注意的是由于iOS中的坐标体系是和Quartz坐标体系中Y轴相反的,所以iOS UIView在做Quartz绘图时,Y轴已经做了Scale为-1的转换,因此造成CGPathAddArc函数最后一个是否是顺时针的参数结果正好是相反的,也就是说如果设置最后的参数为YES,根据参数定义应该是顺时针的,但实际绘图结果会是逆时针的!

    比如,我们设置起点弧度为0,终点弧度为1.5 * PI(等于270角度),然后最后的clockwise参数为NO,代码:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

       

        //创建CGContextRef

        UIGraphicsBeginImageContext(self.view.bounds.size);

        CGContextRef gc = UIGraphicsGetCurrentContext();

       

        //=== 绘画逻辑 ===

        //创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算

        CGAffineTransform transform = CGAffineTransformMakeTranslation(50, 50);

        //创建CGMutablePathRef

        CGMutablePathRef path = CGPathCreateMutable();

        CGPathAddArc(path, &transform, 50, 50, 50, 0, 1.5 * M_PI, NO);

        CGPathMoveToPoint(path, &transform, 50, 0);

        CGPathAddLineToPoint(path, &transform, 50, 50);

        CGPathAddLineToPoint(path, &transform, 100, 50);

       

        //将CGMutablePathRef添加到当前Context内

        CGContextAddPath(gc, path);

        [[UIColor grayColor] setFill];

        [[UIColor blueColor] setStroke];

        CGContextSetLineWidth(gc, 2);

        //执行绘画

        CGContextDrawPath(gc, kCGPathFillStroke);

       

        //从Context中获取图像,并显示在界面上

        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

       

        UIImageView *imgView = [[UIImageView alloc] initWithImage:img];

        [self.view addSubview:imgView];

    }

    输出:

    屏幕快照 2013-11-15 下午11.22.21

    结果会是顺时针绘制弧线.

    如果把CGPathAddArc函数改成这样:

    //虽然顺时针参数是YES,在iOS中的UIView中,这里实际是逆时针。所以只会画出1/4。

    CGPathAddArc(path, &transform, 50, 50, 50, 0, 1.5 * M_PI, YES);

    虽然顺时针参数是YES,在iOS中,这里实际是逆时针。所以只会画出1/4。结果会是:

    屏幕快照 2013-11-15 下午11.44.54

    而CGContextAddArcToPoint函数则是另一种绘制弧线的方式,同样可以参考那个SO回答的截图.它是通过画两个虚拟的线来完成绘图的,这两条线是通过当前CGContextRef的点,和CGContextAddArcToPoint函数本身定义的两个点来完成的。而弧线会从当前CGContextRef的点开始,画到中心圆与第二条线的交点处。这样的画弧方式,在某些情况下可以使CGContextAddArcToPoint函数比CGPathAddArc用起来更加方便些。比如花圆角矩形。

    示例,我们来完成这样一个绘图:

    屏幕快照 2013-11-16 上午12.11.41

    使用CGContextAddArcToPoint函数,我们就可以不去关心太多花弧时的弧度相关数据,而只需要指定矩形的顶点坐标,因为这个弧线是依赖两个顶点坐标所围成的空间的,这正是CGContextAddArcToPoint发挥作用的地方。实现代码:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

       

        //创建CGContextRef

        UIGraphicsBeginImageContext(self.view.bounds.size);

        CGContextRef gc = UIGraphicsGetCurrentContext();

       

        //=== 绘画逻辑 ===

        //创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算

        CGAffineTransform transform = CGAffineTransformMakeTranslation(50, 50);

        //创建CGMutablePathRef

        CGMutablePathRef path = CGPathCreateMutable();

        //半径为30

        CGFloat radius = 30;

        //初始点为(0, 0)

        CGPathMoveToPoint(path, &transform, 0, 0);

        //右上角和右下角两个点,画出半个圆角

        CGPathAddArcToPoint(path, &transform, 100, 0, 100, 100, radius);

        //右下角和左下角两个点,画出另外半个圆角

        CGPathAddArcToPoint(path, &transform, 100, 100, 0, 100, radius);

        //CGPathAddArcToPoint会在交点中停止,所以需要再次调用CGPathAddLineToPoint画出下面的线

        CGPathAddLineToPoint(path, &transform, 0, 100);

       

        //将CGMutablePathRef添加到当前Context内

        CGContextAddPath(gc, path);

        [[UIColor grayColor] setFill];

        [[UIColor blueColor] setStroke];

        CGContextSetLineWidth(gc, 2);

        //执行绘画

        CGContextDrawPath(gc, kCGPathFillStroke);

       

        //从Context中获取图像,并显示在界面上

        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

       

        UIImageView *imgView = [[UIImageView alloc] initWithImage:img];

        [self.view addSubview:imgView];

    }

  • 相关阅读:
    矩阵运算(二维数组)
    AndroidManifest.xml
    单位和尺寸
    java Map集合类
    http相关
    文件管理与XMl、JSON解析
    Handler与多线程
    App内容分享
    Fragment以及懒加载
    广播接收器与短信
  • 原文地址:https://www.cnblogs.com/nngh/p/4819234.html
Copyright © 2020-2023  润新知