iOS 绘图

作者: gaookey | 来源:发表于2020-09-21 22:21 被阅读0次

概述

在iOS系统中,所有显示在屏幕中的绘画,不管是通过 OpenGLQuartzUIKit,还是Core Animation,都是局限在 UIView 对象或者其子类的对象中。如果用的是系统定义的 UIView,绘画过程是自动进行的。如果自定义 UIView,那么我们自己定义绘画的代码。
除了直接绘画在屏幕上,UIKit框架还提供了屏幕外的 bitmapPDF 图形上下文(graphics contexts)。如果是这类的,那么 view 的绘画循环是不适合这个情况的。

UIView 的绘图循环

UIView 需要第一次显示或者 view 的一部分需要重绘,UIViewdrawRect: 方法会被调用进行重绘。

需要重绘的情况:

  1. 移动或者去除遮挡你的 view 的其它 view

  2. hidden 属性设为 NO 让其他的隐藏的 view 重新显示

  3. view 滚动出屏幕,然后又重新进入屏幕

  4. 主动调用 setNeedsDisplay 或者 setNeedsDisplayInRect 方法

UIKit 和 Core Graphics 两个框架都支持绘图:

Core Graphics 中涉及绘图的主要有 Graphics contexts,Paths,Images and bitmaps,Transparency layers,Colors,pattern colors,and color spacesGradients and shadings 等

UIKit 中涉及绘图的主要有 UIImageUIColorUIFontUIScreenUIBezierPath

Graphics contexts

要绘图必须有一个 graphics contexts,这个对象可以理解成一个画布,所有的东西都要在这上面进行。drawRect:drawLayer: inContext:UIGraphicsBeginImageContextWithOptions 这个三个方法中都可以去获得 Graphic Context 从而绘制图形。

例如我们想画一个矩形,边框是蓝色的,宽度是20,填充红色

image.png

这样就存在 6 种绘图的方式:

方式一:在 UIViewdrawRect: 方法中用 Core Graphics 框架实现

swift

    override func draw(_ rect: CGRect) {
        let ctx = UIGraphicsGetCurrentContext()
        ctx?.setLineWidth(20)
        ctx?.setStrokeColor(UIColor.blue.cgColor)
        ctx?.setFillColor(UIColor.red.cgColor)
        ctx?.addRect(CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height))
        ctx?.drawPath(using: .fillStroke)
    }

oc

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(ctx, 20);
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
    CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
    CGContextAddRect(ctx, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
    CGContextDrawPath(ctx, kCGPathFillStroke);
}
方式二:在 UIViewdrawRect: 方法中用 UIKit 框架实现

swift

    override func draw(_ rect: CGRect) {
        let path = UIBezierPath(rect: CGRect(x: 10, y: 10, width: bounds.width - 20, height: bounds.height - 20))
        path.lineWidth = 20
        UIColor.blue.setStroke()
        UIColor.red.setFill()
        path.stroke()
        path.fill()
    }

oc

- (void)drawRect:(CGRect)rect {
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, self.bounds.size.width - 20, self.bounds.size.height - 20)];
    path.lineWidth = 20;
    [[UIColor blueColor] setStroke];
    [[UIColor redColor] setFill];
    [path stroke];
    [path fill];
}
方式三:在 CALayer 的代理方法 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx; 中用 Core Graphics 框架实现

swift

import UIKit

class ViewController: UIViewController, CALayerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myLayer = CALayer()
        myLayer.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
        myLayer.delegate = self
        view.layer.addSublayer(myLayer)
        myLayer.setNeedsDisplay() 
    }
    
    func draw(_ layer: CALayer, in ctx: CGContext) {
        ctx.setLineWidth(20)
        ctx.setStrokeColor(UIColor.blue.cgColor)
        ctx.setFillColor(UIColor.red.cgColor)
        ctx.addRect(CGRect(x: 0, y: 0, width: layer.bounds.width, height: layer.bounds.height))
        ctx.drawPath(using: .fillStroke)
    } 
}

oc

#import "ViewController.h"

@interface ViewController () <CALayerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
     
    CALayer *myLayer = [CALayer layer];
    myLayer.frame = CGRectMake(100, 100, 200, 200);
    myLayer.delegate = self;
    [self.view.layer addSublayer:myLayer];
    [myLayer setNeedsDisplay]; 
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    CGContextSetLineWidth(ctx, 20);
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
    CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
    CGContextAddRect(ctx, CGRectMake(0, 0, layer.bounds.size.width, layer.bounds.size.height));
    CGContextDrawPath(ctx, kCGPathFillStroke);
}

@end
方式四:在 CALayer 的代理方法 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx; 中用 UIKit 框架实现

swift

import UIKit

class ViewController: UIViewController, CALayerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myLayer = CALayer()
        myLayer.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
        myLayer.delegate = self
        view.layer.addSublayer(myLayer)
        myLayer.setNeedsDisplay()
    }
    
    func draw(_ layer: CALayer, in ctx: CGContext) {
        UIGraphicsPushContext(ctx)
        let path = UIBezierPath(rect: CGRect(x: 10, y: 10, width: layer.bounds.width - 20, height: layer.bounds.height - 20))
        path.lineWidth = 20
        UIColor.blue.setStroke()
        UIColor.red.setFill()
        path.stroke()
        path.fill()
        UIGraphicsPopContext()
    }
}

oc

#import "ViewController.h"

@interface ViewController () <CALayerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CALayer *myLayer = [CALayer layer];
    myLayer.frame = CGRectMake(100, 100, 200, 200);
    myLayer.delegate = self;
    [self.view.layer addSublayer:myLayer];
    [myLayer setNeedsDisplay];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    UIGraphicsPushContext(ctx);
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, layer.bounds.size.width - 20, layer.bounds.size.height - 20)];
    path.lineWidth = 20;
    [[UIColor blueColor] setStroke];
    [[UIColor redColor] setFill];
    [path stroke];
    [path fill];
    UIGraphicsPopContext();
}

@end
方式五:用 UIGraphicsBeginImageContextWithOptionsUIKit 框架实现

swift

        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), false, 0)
        
        let path = UIBezierPath(rect: CGRect(x: 10, y: 10, width: 200 - 20, height: 200 - 20))
        path.lineWidth = 20
        UIColor.blue.setStroke()
        UIColor.red.setFill()
        path.stroke()
        path.fill()
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        let imageView = UIImageView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
        imageView.image = image
        view.addSubview(imageView)

oc

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0);
    
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 200, 200)];
    [path setLineWidth:20];
    [[UIColor redColor] setFill];
    [[UIColor blueColor] setStroke];
    [path fill];
    [path stroke];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    imageView.image = image;
    [self.view addSubview:imageView];
方式六:用 UIGraphicsBeginImageContextWithOptionsCore Graphics 框架实现

swift

        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), false, 0)
        
        let ctx = UIGraphicsGetCurrentContext()
        ctx?.setLineWidth(20)
        ctx?.setStrokeColor(UIColor.blue.cgColor)
        ctx?.setFillColor(UIColor.red.cgColor)
        ctx?.addRect(CGRect(x: 0, y: 0, width: 200, height: 200))
        ctx?.drawPath(using: .fillStroke)
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        let imageView = UIImageView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
        imageView.image = image
        view.addSubview(imageView)

oc

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(ctx, 20);
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
    CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
    CGContextAddRect(ctx, CGRectMake(0, 0, 200, 200));
    CGContextDrawPath(ctx, kCGPathFillStroke);
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    imageView.image = image;
    [self.view addSubview:imageView];

画直线

我们可以通过 Core GraphicsUIKit 框架画直线

Core Graphics

image.png
- (void)drawRect:(CGRect)rect {
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);//设置线的颜色
    CGContextSetLineWidth(ctx, 5);//设置线的宽度
    CGContextSetLineCap(ctx, kCGLineCapRound);//设置线的起始端的样式
    CGContextSetLineJoin(ctx, kCGLineJoinRound);//设置线的连接样式
    
    //设置虚线
    CGFloat length[] = {10 , 5, 10};
    CGContextSetLineDash(ctx, 8, length, 3);
    
    //画一条线
    CGContextMoveToPoint(ctx, 10, 50);
    CGContextAddLineToPoint(ctx, 100, 50);
    //同时依次画多条线
    CGPoint lines[] = {
        CGPointMake(10.0, 90.0),
        CGPointMake(70.0, 60.0),
        CGPointMake(130.0, 90.0),
        CGPointMake(190.0, 60.0),
        CGPointMake(250.0, 90.0),
        CGPointMake(310.0, 60.0),
    };
    
    //参数二:线数组,参数三:线的个数
    CGContextAddLines(ctx, lines, sizeof(lines)/sizeof(lines[0]));
    
    CGContextStrokePath(ctx);
}

UIKit

image.png
- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    //设置虚线
    CGFloat length[] = {10, 5, 10};
    [path setLineDash:length count:3 phase:8];
    
    [path moveToPoint:CGPointMake(10, 50)];
    [path addLineToPoint:CGPointMake(100, 50)];
    path.lineWidth = 2;
    [[UIColor redColor] setStroke];
    [path stroke];
      
    path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(10.0, 90.0)];
    [path addLineToPoint:CGPointMake(70.0, 60.0)];
    [path addLineToPoint:CGPointMake(130.0, 90.0)];
    [path addLineToPoint:CGPointMake(190.0, 60.0)];
    [path addLineToPoint:CGPointMake(250.0, 90.0)];
    [path addLineToPoint:CGPointMake(310.0, 60.0)];
    path.lineWidth = 5;
    [path stroke];
}

画弧线

CGContext 实现

image.png
- (void)drawRect:(CGRect)rect {
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);//设置线的颜色
    CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);//设置填充颜色
    CGContextSetLineWidth(ctx, 2); //设置线的宽度
    
    CGContextAddEllipseInRect(ctx, CGRectMake(10, 30, 60, 60)); //画一个椭圆或者圆
    CGContextDrawPath(ctx, kCGPathFillStroke);
    //根据中心点,半径,起始的弧度,最后的弧度,是否顺时针画一个圆弧
    CGContextAddArc(ctx, 140, 60, 30, M_PI/2.f, M_PI, 1);
    CGContextDrawPath(ctx, kCGPathStroke);
    
    CGPoint p[3] =
    {
        CGPointMake(210.0, 30.0),
        CGPointMake(210.0, 60.0),
        CGPointMake(240.0, 60.0),
    };
    //先移到p1点
    CGContextMoveToPoint(ctx, p[0].x, p[0].y);
    //从p1点开始画弧线,圆弧和p1-p2相切;p2-p3和弧线相切,圆弧的半径是20
    CGContextAddArcToPoint(ctx, p[1].x, p[1].y, p[2].x, p[2].y, 20.0);
    CGContextStrokePath(ctx);
    
    //画一个圆角矩形
    CGRect rrect = CGRectMake(210.0, 70.0, 60.0, 60.0);
    CGFloat radius = 10.0;
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);
    CGContextMoveToPoint(ctx, minx, midy);
    CGContextAddArcToPoint(ctx, minx, miny, midx, miny, radius);
    CGContextAddArcToPoint(ctx, maxx, miny, maxx, midy, radius);
    CGContextAddArcToPoint(ctx, maxx, maxy, midx, maxy, radius);
    CGContextAddArcToPoint(ctx, minx, maxy, minx, midy, radius);
    CGContextClosePath(ctx);
    CGContextDrawPath(ctx, kCGPathFillStroke);
    
    //贝塞尔曲线一,两个控制点
    CGPoint s = CGPointMake(30.0, 120.0); //起始点
    CGPoint e = CGPointMake(300.0, 120.0);//终点
    CGPoint cp1 = CGPointMake(120.0, 30.0);//控制点1
    CGPoint cp2 = CGPointMake(210.0, 210.0);//控制点2
    CGContextMoveToPoint(ctx, s.x, s.y);
    CGContextAddCurveToPoint(ctx, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);
    CGContextStrokePath(ctx);
    
    //贝塞尔曲线二,一个控制点
    s = CGPointMake(30.0, 300.0);
    e = CGPointMake(270.0, 300.0);
    cp1 = CGPointMake(150.0, 180.0);
    CGContextMoveToPoint(ctx, s.x, s.y);
    CGContextAddQuadCurveToPoint(ctx, cp1.x, cp1.y, e.x, e.y);
    CGContextStrokePath(ctx);
}

UIKit 实现

image.png
- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(10, 30, 60, 60)];
    [[UIColor redColor] setStroke];
    [[UIColor blueColor] setFill];
    path.lineWidth = 2;
    [path stroke];
    [path fill];
    
    path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(140, 60) radius:30 startAngle:M_PI/2.f endAngle:M_PI clockwise:YES];
    path.lineWidth = 2;
    [path stroke];
    
    path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(210, 70, 60, 60) cornerRadius:5];
    path.lineWidth = 2;
    [path stroke];
    [path fill];
    
    path = [UIBezierPath bezierPath];
    path.lineWidth = 2;
    CGPoint s = CGPointMake(30.0, 120.0);
    CGPoint e = CGPointMake(300.0, 120.0);
    CGPoint cp1 = CGPointMake(120.0, 30.0);
    CGPoint cp2 = CGPointMake(210.0, 210.0);
    [path moveToPoint:s];
    [path addCurveToPoint:e controlPoint1:cp1 controlPoint2:cp2];
    [path stroke];
    
    path = [UIBezierPath bezierPath];
    path.lineWidth = 2;
    s = CGPointMake(30.0, 300.0);
    e = CGPointMake(270.0, 300.0);
    cp1 = CGPointMake(150.0, 180.0);
    [path moveToPoint:s];
    [path addQuadCurveToPoint:e controlPoint:cp1];
    [path stroke];
}

绘制文字和图像

绘制图形和文字之前需要了解两个坐标系统。

Upper-left-origin coordinate system (ULO):左上为起始点的坐标系统,UIKitCore Animation 框架用的是这个坐标系统。

Lower-left-origin coordinate system (LLO):左下为起始点坐标系统,Core Graphics 框架是这个坐标系统。

这两个不同的坐标系统的不同,就必然需要 Core Graphics 绘制的图片需要上下翻转,才能正常在 UIView 中显示。 此外,UIImageNSString 可以直接绘制,所以不需要像前面绘制圆弧,直线等一样去用 UIBezierPath 类去绘制了。

实现方法一:通过 UIViewdrawInRect: 方法内用 UIKit 框架实现
[image drawInRect:CGRectMake(20, 20, 200, 200)];
[@"这是一段文字" drawAtPoint:CGPointMake(10, 120) withAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14], NSForegroundColorAttributeName: [UIColor blackColor]}];

图片操作

    /// 调整图片大小
    func resizeImage(image: UIImage, toSize: CGSize) -> UIImage {
        
        if UIScreen.main.scale == 2.0 {
            UIGraphicsBeginImageContextWithOptions(toSize, false, 2.0)
        } else if UIScreen.main.scale == 3.0 {
            UIGraphicsBeginImageContextWithOptions(toSize, false, 3.0)
        } else {
            UIGraphicsBeginImageContext(toSize)
        }
        
        image.draw(in: CGRect(x: 0, y: 0, width: toSize.width, height: toSize.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage!
    }
    
    /// 比例缩放图片
    func scaleImage(image: UIImage, toScale: CGFloat) -> UIImage {
        
        if UIScreen.main.scale == 2.0 {
            UIGraphicsBeginImageContextWithOptions(CGSize(width: image.size.width * toScale, height: image.size.height * toScale), false, 2.0)
        } else if UIScreen.main.scale == 3.0 {
            UIGraphicsBeginImageContextWithOptions(CGSize(width: image.size.width * toScale, height: image.size.height * toScale), false, 3.0)
        } else {
            UIGraphicsBeginImageContext(CGSize(width: image.size.width * toScale, height: image.size.height * toScale))
        }
        
        image.draw(in: CGRect(x: 0, y: 0, width: image.size.width * toScale, height: image.size.height * toScale))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage!
    }
实现方法二:通过 UIViewdrawInRect: 方法内用 Core Graphics 框架实现
- (void)drawRect:(CGRect)rect {
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    //翻转起来---上下颠倒
    CGContextTranslateCTM(ctx, 0.0, self.bounds.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);
    
    //假设想在 (10, 20, 80, 100) 的地方绘制,颠倒过来后的 Rect 应该是 (10, self.bounds.size.height - (100 + 20), 80, 80)
    CGRect imageRect = CGRectMake(10, self.bounds.size.height - (100 + 20), 80, 100);
    CGContextDrawImage(ctx, imageRect, [UIImage imageNamed:@"image.jpeg"].CGImage);
    CGContextRestoreGState(ctx);
}
方法三:通过 UIGraphicsBeginImageContextWithOptions 方便的创建图片
    UIGraphicsBeginImageContext(CGSizeMake(80, 100));
    [[UIImage imageNamed:@"image.jpeg"] drawInRect: CGRectMake(0, 0, 80, 80)];
    [@"这是一段文字" drawAtPoint: CGPointMake(0, 50) withAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14], NSForegroundColorAttributeName: [UIColor blackColor]}];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

绘制渐变

iOS Core Graphics 的渐变可以分成径向渐变和辐射渐变。可以实现如下的图形:

可以在 view- (void)drawRect:(CGRect)rect 实现
image.png
- (void)drawRect:(CGRect)rect {
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //创建一个RGB的颜色空间
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    //定义渐变颜色数组
    CGFloat colors[] =
    {
        204.0 / 255.0, 224.0 / 255.0, 244.0 / 255.0, 1.00,
        29.0 / 255.0, 156.0 / 255.0, 215.0 / 255.0, 1.00,
        0.0 / 255.0,  50.0 / 255.0, 126.0 / 255.0, 1.00,
    };
    
    //创建一个渐变的色值 1:颜色空间 2:渐变的色数组 3:位置数组,如果为NULL,则为平均渐变,否则颜色和位置一一对应 4:位置的个数
    CGGradientRef _gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));
    CGColorSpaceRelease(rgb);
    
    //获得一个CGRect
    CGRect clip = CGRectInset(CGContextGetClipBoundingBox(ctx), 20.0, 20.0);
    //剪切到合适的大小
    CGContextClipToRect(ctx, clip);
    //定义起始点和终止点
    CGPoint start = CGPointMake(20, 20);
    CGPoint end = CGPointMake(20, 100);
    //绘制渐变, 颜色的0对应start点,颜色的1对应end点,第四个参数是定义渐变是否超越起始点和终止点
    CGContextDrawLinearGradient(ctx, _gradient, start, end, kCGGradientDrawsBeforeStartLocation);
    
    //辐射渐变
    start = CGPointMake(100, 80);//起始点
    end = CGPointMake(100, 140); //终结点
    //辐射渐变 start:起始点 20:起始点的半径 end:终止点 40: 终止点的半径 这个辐射渐变
    CGContextDrawRadialGradient(ctx, _gradient, start, 20, end, 40, 0);
}
UIKit 提供一个 CALayer 的子类,专门绘制渐变,但是只支持线性渐变
image.png
    CAGradientLayer *gradient = [CAGradientLayer layer];//创建渐变层
    gradient.frame = CGRectMake(100, 100, 200, 200);
    [self.view.layer addSublayer:gradient];
    //渐变层的颜色梯度数组
    gradient.colors = @[(__bridge id)[UIColor colorWithRed:204.0 / 255.0 green:224.0 / 255.0 blue:244.0 / 255.0 alpha:1].CGColor,
                        (__bridge id)[UIColor colorWithRed:29.0 / 255.0 green:156.0 / 255.0 blue:215.0 / 255.0 alpha:1].CGColor,
                        (__bridge id)[UIColor colorWithRed:0.0 / 255.0 green:50.0 / 255.0 blue:126.0 / 255.0 alpha:1].CGColor];
    //渐变层的相对位置,起始点为0,终止点为1,中间点为 (point-startpoint)/(endpoint-startpoint)
    gradient.locations = @[@0,@.5,@1];
    //渐变方向
    gradient.startPoint = CGPointMake(0, 0);
    gradient.endPoint = CGPointMake(0, 1);

利用 CAShapeLayer、UIBezierPath、CGPath 绘制图像

iOS 提供了一个 CALayer 类,专门负责负责绘制 CGPath 显示内容。最方便的方法是利用 UIBezierPath 绘制的 CGPath,或者直接创建的 CGPath 进行图形的绘制。

例如我们想根据圆弧标示进展。那么我们如何绘制呢

image.png
1. CAShapeLayerUIBezierPath 的组合:
    for (int i = 0; i < 4; i ++) {
        CAShapeLayer *layerOne = [CAShapeLayer layer];
        layerOne.frame = CGRectMake(50 + 80 * i, 100, 60, 60);
        
        UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 60, 60)];
        layerOne.path = circlePath.CGPath;
        //只是借用Path,不能借用图形设置,必须设置在layer中哦
        layerOne.fillColor = [UIColor whiteColor].CGColor;
        layerOne.lineWidth = 2;
        layerOne.strokeColor = [UIColor blueColor].CGColor;
        
        [self.view.layer addSublayer:layerOne];
        
        CAShapeLayer *layerTwo = [CAShapeLayer layer];
        CGRect frame = layerOne.frame;
        frame.origin.x += 4;
        frame.origin.y += 4;
        frame.size.width -= 8;
        frame.size.height -= 8;
        layerTwo.frame = frame;
        
        UIBezierPath *innerpath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(26, 26) radius:frame.size.width/2 startAngle:0 endAngle:M_PI*(i+1)/3.f clockwise:YES];
        [innerpath addLineToPoint:CGPointMake(26, 26)];
        [innerpath closePath];
        layerTwo.path = innerpath.CGPath;
        layerTwo.fillColor = [UIColor blueColor].CGColor;
        [self.view.layer addSublayer:layerTwo];
    }
2. CAShapeLayerCGPath 的组合:
    for (int i = 0; i < 4; i ++) {
        CAShapeLayer *layerOne = [CAShapeLayer layer];
        layerOne.frame = CGRectMake(50 + 80 * i, 100, 60, 60);
        
        CGMutablePathRef circlePath = CGPathCreateMutable();
        CGPathAddEllipseInRect(circlePath, NULL, CGRectMake(0, 0, 60, 60));
        
        layerOne.path = circlePath;
        layerOne.fillColor = [UIColor whiteColor].CGColor;
        layerOne.lineWidth = 2;
        layerOne.strokeColor = [UIColor blueColor].CGColor;
        CGPathRelease(circlePath);
        
        [self.view.layer addSublayer:layerOne];
        
        CAShapeLayer *layerTwo = [CAShapeLayer layer];
        CGRect frame = layerOne.frame;
        frame.origin.x += 4;
        frame.origin.y += 4;
        frame.size.width -= 8;
        frame.size.height -= 8;
        layerTwo.frame = frame;
        
        CGMutablePathRef innerPath = CGPathCreateMutable();
        CGPathAddArc(innerPath, NULL, 26, 26, frame.size.width/2, 0, M_PI*(i+1)/3.f, NO);
        CGPathAddLineToPoint(innerPath, NULL, 26, 26);
        CGPathCloseSubpath(innerPath);
        layerTwo.path = innerPath;
        layerTwo.fillColor = [UIColor blueColor].CGColor;
        [self.view.layer addSublayer:layerTwo];
    }

相关文章

  • iOS绘图详解(链接)

    iOS绘图详解iOS绘图教程

  • iOS 绘图

    转自:iOS绘图—— UIBezierPath 和 Core Graphics绘图进阶请参考:绘图 前言 iOS系...

  • iOS绘图框架CoreGraphics分析

    iOS绘图框架CoreGraphics分析 iOS绘图框架CoreGraphics分析

  • IOS 学习之绘图( Core Graphics 教学)

    IOS 绘图 总结 Core Graphics IOS中绘图的三种方式 在UIKit控件中,的drawInReat...

  • ios绘图基础

    ios绘图才一些场合很好用,这里演示一些基本的方法。 -1 ios绘图基础 -2 ios常见的图形绘制 代码下载:...

  • 绘图

    IOS中绘图的方式介绍 IOS中貌似绘图的方式还挺多的,有 Core Graphics/QuartZ 2D UIK...

  • iOS绘图功能(一)

    不同的绘图系统### iOS主要的绘图系统有UIKit,Core Graphics(Quartz), Core A...

  • 绘图1

    iOS中绘图的概念 iOS iOSopenGL Quartz UIView DrawRect 1个像素 =...

  • iOS-绘图Quartz 2D 贝赛尔曲线相关

    本篇涵盖iOS中绘图上下文,截屏相关等. 1.玩转iOS中的绘图(Quartz 2D基础篇)2.分享iOS中常用的...

  • iOS Quart2D绘图

    iOS Quart2D绘图之UIGraphicsGetCurrentContext基础。 iOS Quart2D绘...

网友评论

    本文标题:iOS 绘图

    本文链接:https://www.haomeiwen.com/subject/otobyktx.html