OCiOS开发:绘图与曲线

来源:互联网 发布:九浅一深网络剧百度云 编辑:程序博客网 时间:2024/06/08 05:56

简介

  • iOS上,所有的绘制,无论是否采用OpenGL、Quartz、UIKit、或者 Core Animation—都发生在UIView对象的区域内,即子类化UIView,在drawRect方法中进行绘制。

  • 视图定义绘制发生的屏幕区域。如果使用系统提供的视图,绘制工作会自动得到处理。然而,如果定义自己的定制视图,则必须自行提供绘制代码。

Core Graphics 绘图

常用绘图函数

// 1、绘制椭圆CGContextAddEllipseInRect(CGContextRef context, CGRect rect)// 2、绘制虚线CGContextSetLineDash(CGContextRef c, CGFloat phase,  const CGFloat lengths[], size_t count)// 3、绘制圆弧CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,  CGFloat x2, CGFloat y2, CGFloat radius)CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,  CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)// 4、绘制曲线CGContextAddCurveToPoint(CGContextRef c, CGFloat cp1x,  CGFloat cp1y, CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y)// 5、绘制直线 CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)// 6、绘制曲线CGContextAddRect(CGContextRef __nullable c, CGRect rect)

填充

1、为图形填充颜色的几个函数:

// 1、填充矩形CGContextFillRect(context, rectangl);// 2、填充椭圆或圆CGContextFillEllipseInRect(context, rectangle);// 3、填充路径CGContextFillPath(context); 

注意:在填充颜色之前首先要调用 CGContextSetFillColorWithColor() 定制填充颜色。

2、代码示例:

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 创建一个椭圆,如果 width = height 则是一个圆    CGRect rectangle = CGRectMake(100, 100, 200, 200);    CGContextAddEllipseInRect(context, rectangle);    CGContextStrokePath(context);    // 填充    // 1、设置填充颜色    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);    // 2、填充椭圆    CGContextFillEllipseInRect(context, rectangle);}

绘制直线

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 确定第一个点    CGContextMoveToPoint(context, 100, 100);    // 确定第二个点    CGContextAddLineToPoint(context, 200, 300);    // 开始绘图    CGContextStrokePath(context);   }

绘制椭圆

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 创建一个椭圆,如果 width = height 则是一个圆    CGRect rectangle = CGRectMake(100, 100, 200, 200);    CGContextAddEllipseInRect(context, rectangle);    CGContextStrokePath(context);}

绘制三角形

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 创建三个点    CGPoint point1 = CGPointMake(CGRectGetMidX(self.bounds),                                 CGRectGetMidY(self.bounds) - 80);    CGPoint point2 = CGPointMake(CGRectGetMidX(self.bounds) - 80,                                 CGRectGetMidY(self.bounds) + 100);    CGPoint point3 = CGPointMake(CGRectGetMidX(self.bounds) + 80,                                 CGRectGetMidY(self.bounds) + 100);    // 连接三个点    // 1、设置起点    CGContextMoveToPoint(context, point1.x, point1.y);    // 2、设置连接点    CGContextAddLineToPoint(context, point2.x, point2.y);    CGContextAddLineToPoint(context, point3.x, point3.y);    CGContextAddLineToPoint(context, point1.x, point1.y);    // 绘图    CGContextStrokePath(context);}

绘制虚线

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // lengths 指明虚线如何交替绘制    // lengths {10, 10}表示先绘制10个点,再跳过10个点,再绘制10个点,如此反复绘制;    // lengths {5, 10, 5}表示先绘制5个点,再跳过10个点,再绘制5个点,再跳过5个点,如此反复绘制;    CGFloat lengths[] = {10, 10};    // 第1个参数:上下文    // 第2个参数:phase值,如果设值为5,则在绘制第一段的时候执行(n - 5)个点,n为虚线交替绘制方式第1个元素值。    // 第3个参数:虚线交替绘制方式    // 第4个参数:虚线交替绘制方式集合元素个数    CGContextSetLineDash(context, 0, lengths, 2);    // 设置虚线起点    CGContextMoveToPoint(context, 100, 100);    // 设置虚线终点    CGContextAddLineToPoint(context, 300, 300);    // 开始绘制    CGContextStrokePath(context);}

绘制弧线

方法1:

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 设置圆心    CGPoint centerPoint = {200, 300};    // 设置半径    CGFloat radius = 100;    // 设置起始角度    CGFloat startAngle = 0;    // 设置结束角度    CGFloat endAngle = M_PI;    // 设置绘制方向:1为顺时针, 0为逆时针    int clockwise = 1;    // 绘制弧线    // 第1个参数:上下文    // 第2个参数:圆心.x    // 第3个参数:圆心.y    // 第4个参数:半径    // 第5个参数:起始角度    // 第6个参数:结束角度    // 第7个参数:旋转方向    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, startAngle, endAngle, clockwise);    CGContextStrokePath(context);}

方法2:

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 通过指定2个切点,还有角度,调用CGContextAddArcToPoint()绘制。    // 圆弧起点    CGPoint firstPoint = {100 ,300};    CGPoint middlePoint = {200 ,200};    CGPoint endPoint = {300 ,300};    CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);    CGContextAddArcToPoint(context, middlePoint.x, middlePoint.y, endPoint.x, endPoint.y, 130);    CGContextStrokePath(context);}

绘制曲线

- (void)drawRect:(CGRect)rect {    // 获取上下文(画布)    CGContextRef context = UIGraphicsGetCurrentContext();    // 设置线条宽度    CGContextSetLineWidth(context, 3.0);    // 设置线条颜色    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 创建四个点    CGPoint firstPoint = {20, 200};    CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);    // 顶峰点    CGPoint topPoint = {90, 40};    // 低峰点    CGPoint bottomPoint = {230, 360};    // 末尾点    CGPoint endPoint = {300, 200};    // 贝兹曲线是通过一个起始点,然后通过两个控制点,还有一个终止点,调用CGContextAddCurveToPoint()函数绘制。    CGContextAddCurveToPoint(context, topPoint.x, topPoint.y, bottomPoint.x, bottomPoint.y, endPoint.x, endPoint.y);    CGContextStrokePath(context);}

注意:如果需要绘制多个峰值,可继续绘制曲线,只需将二次绘制曲线起点置为上一次曲线终点即可。

UIBezierPath 绘图

绘制多边形

- (void)drawRect:(CGRect)rect {    // 设置画笔颜色    [[UIColor redColor] setStroke];    UIBezierPath * path = [[UIBezierPath alloc]init];    // 设置起点    [path moveToPoint:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds))];    // 添加点    [path addLineToPoint:CGPointMake(100, 100)];    [path addLineToPoint:CGPointMake(120, 80)];    [path addLineToPoint:CGPointMake(150, 100)];    // 封闭路径    [path closePath];    // 设直线条宽度    [path setLineWidth:2];    // 设置拐角处的效果为圆角    [path setLineJoinStyle:kCGLineJoinRound];    // 设置结束处的效果为圆角    [path setLineCapStyle:kCGLineCapRound];    // 开始绘制    [path stroke];    // 填充    // 1、设置填充颜色    [[UIColor brownColor] setFill];    // 2、开始填充    [path fill];}

绘制弧形

- (void)drawRect:(CGRect)rect {    // 设置填充颜色    [[UIColor redColor] setFill];    UIBezierPath * path = [[UIBezierPath alloc]init];    // 设置圆心    [path moveToPoint:CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds))];    // 画弧    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));    [path addArcWithCenter:center // 圆心                    radius:80     // 半径                startAngle:0      // 起始角度                  endAngle:M_PI_2 // 结束角度                 clockwise:YES];  // 是否顺时针    // 封闭路径    [path closePath];    // 填充    [path fill];}

注意:以上绘图直接在drawRect方法里面执行,如果不在此方法中执行,需要通过CAShapeLayer类渲染。

拓展

CAShapeLayer实现动画绘制

  • 效果展示

    这里写图片描述

  • 代码示例

- (void)viewDidLoad {    [super viewDidLoad];    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];    shapeLayer.frame = CGRectMake(0, 0, 150, 150);    // 使用position来确定layer的位置    shapeLayer.position = self.view.center;    // clockwise控制顺时针或逆时针    // 绘制路径,画圆    shapeLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(shapeLayer.bounds), CGRectGetMidY(shapeLayer.bounds)) radius:CGRectGetMidX(shapeLayer.bounds) startAngle:0 endAngle:2 * M_PI clockwise:YES].CGPath;    // 设置图层的路径渲染颜色    shapeLayer.strokeColor = [UIColor blueColor].CGColor;    // 设置图层的填充颜色    shapeLayer.fillColor = [UIColor clearColor].CGColor;    // 设置路径宽度    shapeLayer.lineWidth = 2;    [self.view.layer addSublayer:shapeLayer];    // 使用高级动画中的基本动画,做渲染的关键字为strokeEnd    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];    // 设置持续时间    basicAnimation.duration = 3;    // 设置起始帧    basicAnimation.fromValue = @0;    // 设置结束帧    basicAnimation.toValue = @1;    // 设置重复次数    basicAnimation.repeatCount = HUGE_VAL;    // 设置是否反向执行    basicAnimation.autoreverses = NO;    // 用一个字符串标识这个动画,内容是任意的。    [shapeLayer addAnimation:basicAnimation forKey:@"strokeEnd"];}

触摸绘图

  • 效果展示

    这里写图片描述

  • 代码示例

#import "DrawingView.h"enum {    undoTag = 100, clearTag};@interface DrawingView () {    NSMutableArray *_lines; /**< 存储绘制的线 */}@end@implementation DrawingView- (instancetype)initWithFrame:(CGRect)frame {    if (self = [super initWithFrame:frame]) {        self.backgroundColor = [UIColor whiteColor];        // 初始化集合        _lines = [NSMutableArray array];        // 撤销        UIButton *undoButton = [UIButton buttonWithType:UIButtonTypeSystem];        undoButton.bounds = CGRectMake(0, 0, 50, 40);        undoButton.center = CGPointMake(self.bounds.size.width - 50, 55);        [self setButtonAttributeWithButton:undoButton title:@"撤销" tag:undoTag];        [self addSubview:undoButton];        // 清空        UIButton *clearButton = [UIButton buttonWithType:UIButtonTypeSystem];        clearButton.bounds = CGRectMake(0, 0, 50, 40);        clearButton.center = CGPointMake(40, 55);        [self setButtonAttributeWithButton:clearButton title:@"清空" tag:clearTag];        [self addSubview:clearButton];    }    return self;}- (void)drawRect:(CGRect)rect {    // 异常处理    if (_lines.count == 0) {        return;    }    // 解决点点击之后再绘制奔溃的问题    [_lines removeObject:@[]];    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSetLineWidth(context, 3.0);    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);    // 步骤:取出一条线 -》 取得线上的每一个点 -》绘图    for (int i = 0; i < _lines.count; i++) {        NSMutableArray *points = _lines[i];        for (int j = 0; j < points.count - 1; j++) {            CGPoint currentPoint = [points[j] CGPointValue];            CGPoint nextPoint = [points[j + 1] CGPointValue];            // 连接两点            CGContextMoveToPoint(context, currentPoint.x, currentPoint.y);            CGContextAddLineToPoint(context, nextPoint.x, nextPoint.y);        }    }    // 开始绘制    CGContextStrokePath(context);}#pragma mark - Touches methods- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    NSMutableArray *newPoints = [NSMutableArray array];    [_lines addObject:newPoints];}- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {    UITouch *touch = [touches anyObject];    CGPoint point = [touch locationInView:self];    NSValue *value = [NSValue valueWithCGPoint:point];    [_lines.lastObject addObject:value];    // 调用此方法会直接调用drawRect方法    [self setNeedsDisplay];}#pragma mark - Private methods- (void)setButtonAttributeWithButton:(UIButton *)button title:(NSString *)title tag:(NSInteger)tag {    button.tag = tag;    button.layer.borderWidth = 0.5;    button.layer.borderColor = [UIColor blackColor].CGColor;    button.layer.cornerRadius = 6;    [button setTitle:title forState:UIControlStateNormal];    [button addTarget:self action:@selector(respondsToButton:) forControlEvents:UIControlEventTouchUpInside];}#pragma mark - responds events- (void)respondsToButton:(UIButton *)sender {    switch (sender.tag) {        case undoTag: {            [_lines removeLastObject];            [self setNeedsDisplay];        }            break;        case clearTag: {            [_lines removeAllObjects];            [self setNeedsDisplay];        }        default:            break;    }}@end

注意:DrawingViewUIView的子类;

0 0
原创粉丝点击