贝塞尔曲线

iOS 三种线的绘制方式 : CGContextRef CG

2019-03-05  本文已影响0人  王技术

都是平时常用的东西
不整理一下的话总感觉有点乱
这三种东西:CGContextRef CGPath UIBezierPath
本质上都是一样的
都是使用 Quartz 来绘画
只不过把绘图操作暴露在不同的 API 层面上
在具体实现上
也会有一些细小的差别


1 - UIBezierPath 方式

首先使用 UIBezierPath 类型绘制
UIBezierPath 包装了Quartz的相关API
自己存在于UIKit中
因此不是基于C的API
而是基于Objective-C对象的
绘制流程 :

- (void)modeUIBezierPath {
    // 开启一个与屏幕大小一样的图形上下文
    UIGraphicsBeginImageContext(self.view.bounds.size);
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 20, 20)]];
    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(80, 0, 20, 20)]];
    [path moveToPoint:CGPointMake(100, 50)];
    // 注意这里 clockwise 参数是 YES 而不是 NO,如果是 Quartz,需要考虑Y轴翻转的问题传 NO
    [path addArcWithCenter:CGPointMake(50, 50) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];
    // 可以使用 applyTransform 函数来转移坐标的 Transform
    [path applyTransform:CGAffineTransformMakeTranslation(150, 200)];
    [[UIColor redColor] setStroke];
    [path setLineWidth:2];
    [path stroke];
    
    // 从 Context 中获取图像,并显示在界面上
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
    imgView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:imgView];
}

效果 :


效果图

2 - CGContextRef 方式 :

- (void)modeCGContextRef {
    // 开启一个与屏幕大小一样的图形上下文
    UIGraphicsBeginImageContext(self.view.bounds.size);
    // 获取当前 CGContextRef
    CGContextRef gc = UIGraphicsGetCurrentContext();
    // 可以使用 CGContextTranslateCTM 函数来转移坐标的 Transform
    CGContextTranslateCTM(gc, 150, 200);
    CGContextAddEllipseInRect(gc, CGRectMake(0, 0, 20, 20));
    CGContextAddEllipseInRect(gc, CGRectMake(80, 0, 20, 20));
    CGContextMoveToPoint(gc, 100, 50);
    CGContextAddArc(gc, 50, 50, 50, 0, M_PI, NO);
    [[UIColor redColor] setStroke];
    CGContextSetLineWidth(gc, 2);
    CGContextStrokePath(gc);
    
    // 从 Context 中获取图像,并显示在界面上
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
    imgView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:imgView];
}

效果 :


效果图

3 - CGPath 方式 :

- (void)modeCGPath {
    // 开始图像绘图
    UIGraphicsBeginImageContext(self.view.bounds.size);
    // 获取当前 CGContextRef
    CGContextRef gc = UIGraphicsGetCurrentContext();
    // 可以使用 CGAffineTransformMakeTranslation 函数来转移坐标的 Transform
    CGAffineTransform transform = CGAffineTransformMakeTranslation(150, 200);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddEllipseInRect(path, &transform, CGRectMake(0, 0, 20, 20));
    CGPathAddEllipseInRect(path, &transform, CGRectMake(80, 0, 20, 20));
    CGPathMoveToPoint(path, &transform, 100, 50);
    CGPathAddArc(path, &transform, 50, 50, 50, 0, M_PI, NO);
    // 将 CGMutablePathRef 添加到当前 Context 内
    CGContextAddPath(gc, path);
    [[UIColor redColor] setStroke];
    CGContextSetLineWidth(gc, 2);
    CGContextStrokePath(gc);
    
    // 从 Context 中获取图像,并显示在界面上
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
    imgView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:imgView];
}

效果 :


效果图

另外 :

由于三种方式本质上都是一样的
都是使用Quartz来绘画
使用中很多地方都是互通的
比如 CGPath 和 UIBezierPath 的互转

CGPathRef cgPath = CGPathCreateMutable();
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:cgPath];
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:cgPath];
CGPathRef cgPath = bezierPath.CGPath;

所以上面任何用 CGPath 的地方都可以换成 UIBezierPath
相反也同理

上一篇下一篇

猜你喜欢

热点阅读