iOS之简笔画

最近是有些懒了,本计划一周一篇文章的,现在都变成两周一篇了,需要反省一下。。。

写这篇文章是因为有一次看到说现在的程序员,连基本的绘图都不会,所以就和大家一起学学基本绘图吧。今天说的是绘制一些基本图形,就一些圆啊,三角啊什么的,都比较简单。

    CGContextRef context = UIGraphicsGetCurrentContext();//获取画布
    CGContextSetRGBStrokeColor(context, 1, 1, 0, 1.0);//画笔的颜色
    CGContextSetLineWidth(context, 8.0);//画笔的粗细
    CGContextAddArc(context, 80, 30, 15, 0, 2 * M_PI, 0);//x,y是圆点坐标,radius是半径,startAngle是开始的弧度,endAngle是结束的弧度,clockwise是是否为逆时针(1是0否)
    CGContextDrawPath(context, kCGPathStroke);//完成路径
带边框的圆
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);//设置填充颜色
    CGContextSetLineWidth(context, 3.0);//画笔的粗细
    CGContextAddArc(context, 130, 30, 15, 0, 2 * M_PI, 0);//添加一个圆
    CGContextDrawPath(context, kCGPathFillStroke);//绘制路径并填充
太极图
CGContextAddArc(context, 190, 30, 15, M_PI_2, 1.5 * M_PI, 0);
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextFillPath(context);
    CGContextStrokePath(context);
    
    CGContextAddArc(context, 190, 30, 15, M_PI_2, 1.5 * M_PI, 1);
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillPath(context);
    CGContextStrokePath(context);
    
    CGContextAddArc(context, 190, 22.5, 7.5, M_PI_2, 1.5 * M_PI, 0);
    CGContextFillPath(context);
    CGContextStrokePath(context);
    
    CGContextAddArc(context, 190, 37.5, 7.5, M_PI_2, 1.5 * M_PI, 1);
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextFillPath(context);
    CGContextStrokePath(context);
    
    CGContextAddArc(context, 190, 22.5, 3.75, M_PI_2, 2.5 * M_PI, 0);
    CGContextFillPath(context);
    CGContextStrokePath(context);
    
    CGContextAddArc(context, 190, 37.5, 3.75, M_PI_2, 2.5 * M_PI, 0);
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillPath(context);
    CGContextStrokePath(context);
直线
CGPoint linePoint[2] = {CGPointMake(100, 70),CGPointMake(150, 70)};
    CGContextAddLines(context, linePoint, sizeof(linePoint)/sizeof(CGPoint));//添加线
    CGContextDrawPath(context, kCGPathStroke);
笑脸
    CGContextMoveToPoint(context, 185, 60);//起始坐标
    CGContextAddArcToPoint(context, 200, 40, 210, 60, 14);//x1,y1与起始坐标形成一条直线,x1,y1与x2,y2又形成一条直线,这两条直线确定弧线的形状,radius是半径
    CGContextStrokePath(context);//绘制路径
    
    CGContextMoveToPoint(context, 225, 60);//起始坐标
    CGContextAddArcToPoint(context, 240, 40, 250, 60, 14);//
    CGContextStrokePath(context);//绘制路径
    
    CGContextMoveToPoint(context, 197.5, 75);//起始坐标
    CGContextAddArcToPoint(context, 222, 95, 237.5, 75, 25);//
    CGContextStrokePath(context);//绘制路径
矩形
    CGContextSetFillColorWithColor(context, [UIColor cyanColor].CGColor);//设置填充颜色
    CGContextAddRect(context, CGRectMake(60, 95, 50, 25));//画方框
    CGContextDrawPath(context, kCGPathFillStroke);//绘制路径
    
    //填充1:
    CAGradientLayer * gradientRectangle = [CAGradientLayer layer];
    gradientRectangle.frame = CGRectMake(130, 95, 50, 25);
    gradientRectangle.colors = @[(id)[UIColor redColor].CGColor,(id)[UIColor orangeColor].CGColor,(id)[UIColor yellowColor].CGColor,(id)[UIColor greenColor].CGColor,(id)[UIColor cyanColor].CGColor,(id)[UIColor blueColor].CGColor,(id)[UIColor purpleColor].CGColor];
    [self.layer insertSublayer:gradientRectangle atIndex:0];
    
    //填充2:
    //创建填充颜色
    CGColorSpaceRef rgbColor = CGColorSpaceCreateDeviceRGB();
    CGFloat colors[] ={1,1,1, 1.00,
                       1,1,0, 1.00,
                       1,0,0, 1.00,
                       1,0,1, 1.00,
                       0,1,1, 1.00,
                       0,1,0, 1.00,
                       0,0,1, 1.00,
                       0,0,0, 1.00,};
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgbColor, colors, NULL,sizeof(colors)/(sizeof(colors[0])*4));
    CGColorSpaceRelease(rgbColor);
    
    CGContextSaveGState(context);//记录当前的状态
    CGContextMoveToPoint(context, 200, 95);//起始点
    CGContextAddLineToPoint(context, 220, 95);//与起始点形成一条线
    CGContextAddLineToPoint(context, 220, 120);//与上一个点形成一条线
    CGContextAddLineToPoint(context, 200, 120);//与上一个点形成一条线
    CGContextClip(context);//裁剪路径
    
    CGContextDrawLinearGradient(context, gradient, CGPointMake(200, 95), CGPointMake(220, 120), kCGGradientDrawsAfterEndLocation);//gradient渐变颜色,startPoint开始渐变的起始位置,endPoint结束坐标,options开始坐标之前or开始之后开始渐变
    CGContextRestoreGState(context);//恢复到之前的context
   
    //矩形填充
    CGContextSaveGState(context);
    CGContextMoveToPoint(context, 240, 95);
    CGContextAddLineToPoint(context, 270, 95);
    CGContextAddLineToPoint(context, 270, 120);
    CGContextAddLineToPoint(context, 240, 120);
    CGContextClip(context);
    
    CGContextDrawLinearGradient(context, gradient, CGPointMake(240, 95), CGPointMake(240, 120), kCGGradientDrawsAfterEndLocation);
    CGContextRestoreGState(context);
    
    //圆
    CGContextDrawRadialGradient(context, gradient, CGPointMake(240, 30), 0, CGPointMake(240, 30), 15, kCGGradientDrawsBeforeStartLocation);
扇形
CGContextSetFillColorWithColor(context, [UIColor cyanColor].CGColor);
    
    //以30为半径围绕圆心画指定角度扇形
    CGContextMoveToPoint(context, 130, 170);
    CGContextAddArc(context, 130, 170, 30, -0.8*M_PI_4, -3.2*M_PI_4, 1);
    CGContextClosePath(context);//关闭路径
    CGContextDrawPath(context, kCGPathFillStroke);
椭圆
    CGContextAddEllipseInRect(context, CGRectMake(180, 145, 40, 20));
    CGContextDrawPath(context, kCGPathFillStroke);
六芒星
    CGPoint trianglePoint1[] = {CGPointMake(220, 220),CGPointMake(310, 220),CGPointMake(265, 220 - 45 * sqrtf(3.0))};
    CGContextAddLines(context, trianglePoint1, sizeof(trianglePoint1)/sizeof(CGPoint));
    CGContextClosePath(context);//关闭路径
    CGContextDrawPath(context, kCGPathStroke);

    CGPoint trianglePoint2[] = {CGPointMake(220, 220 - 30 * sqrtf(3.0)),CGPointMake(310, 220 - 30 * sqrtf(3.0)),CGPointMake(265, 220 + 15 * sqrtf(3.0))};
    CGContextAddLines(context, trianglePoint2, sizeof(trianglePoint2)/sizeof(CGPoint));
    CGContextClosePath(context);//关闭路径
    CGContextDrawPath(context, kCGPathStroke);
圆角矩形
    CGFloat width = 160;
    CGFloat height = 260;
    
    CGContextMoveToPoint(context, width, height - 20);//从坐标右边开始
    CGContextAddArcToPoint(context, width, height, width - 20, height, 10);//右下角角度
    CGContextAddArcToPoint(context, 100, height, 100, height - 20, 10);//左下角度数
    CGContextAddArcToPoint(context, 100, 230, width - 20, 230, 10);//左上角
    CGContextAddArcToPoint(context, width, 230, width, height - 20, 10);//右上角
    CGContextClosePath(context);
    CGContextDrawPath(context, kCGPathFillStroke);
曲线
//二次曲线
    CGContextMoveToPoint(context, 120, 300);
    CGContextAddQuadCurveToPoint(context, 160, 300 - 40 * sqrtf(3.0), 200, 300);//控制点坐标和终点坐标
    CGContextAddQuadCurveToPoint(context, 240, 300 + 40 * sqrtf(3.0), 280, 300);
    CGContextStrokePath(context);
    
    //三次曲线
    CGContextSetRGBStrokeColor(context, 0, 1, 0, 1);
    CGContextMoveToPoint(context, 120, 300);
    CGContextAddCurveToPoint(context, 160, 300 - 40 * sqrtf(3.0), 240, 300 + 40 *sqrtf(3.0), 280, 300);
    CGContextStrokePath(context);

然后搞个画板大家可以自己画着玩

画板

画板分为三步:
1.开始画曲线

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    _path = [UIBezierPath bezierPath];
    
    UITouch * myTouch = [touches anyObject];
    CGPoint point = [myTouch locationInView:self];
    
    [_path moveToPoint:point];
    
    NSDictionary * tempDict = @{@"color":[UIColor blueColor],
                                @"line":_path};
    
    [_lineArr addObject:tempDict];
    
    _undoBtn.enabled = YES;
}

2.画完一笔

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch * myTouch = [touches anyObject];
    CGPoint point = [myTouch locationInView:self];
    
    [_path addLineToPoint:point];
    
    [self setNeedsDisplay];
}

3.显示出来

- (void)drawRect:(CGRect)rect
{
    for (int i = 0 ; i < _lineArr.count; i++) {
        NSDictionary * tempDict = _lineArr[i];
        
        UIColor * color = tempDict[@"color"];
        UIBezierPath * line = tempDict[@"line"];
        
        [color setStroke];
        [line setLineWidth:2.0];
        [line stroke];
    }
}

我还增加了撤消和取消撤消功能:

  • 撤消
NSInteger index = self.lineArr.count - 1;

    [self.cancelArr addObject:self.lineArr[index]];

    [self.lineArr removeObjectAtIndex:index];

    [self setNeedsDisplay];
    
    _undoBtn.enabled = self.lineArr.count > 0 ? YES : NO;
    
    _cancelBtn.enabled = self.cancelArr.count > 0 ? YES : NO;

    return index;
  • 取消撤消
    NSInteger index = self.cancelArr.count - 1;

    [self.lineArr addObject:self.cancelArr[index]];

    [self.cancelArr removeObjectAtIndex:index];

    [self setNeedsDisplay];
    
    _undoBtn.enabled = self.lineArr.count > 0 ? YES : NO;
    
    _cancelBtn.enabled = self.cancelArr.count > 0 ? YES : NO;
    
    return index;

大家还可以修改颜色和线条粗细,并且还可以根据我所写的《让所有的开发者都能使用3D Touch》中的测算点击力度功能来实现线条的粗细,我在这里就不写了。关于文中的内容,具体的可以参见Demo来理解,因为比较简单,我就不分文件,写到一个文件里了,欢迎大家Star.

版权声明:本文为 Crazy Steven 原创出品,欢迎转载,转载时请注明出处!

推荐阅读更多精彩内容