ios绘图demo,做一个涂鸦板(下)

之前一篇ios绘图demo,做一个涂鸦板(上) 完成了一个基本功能的绘图板,这一篇,最要是增加一个画贝塞尔曲线的功能。

ios绘图基础

ios绘图demo,做一个涂鸦板(上)

  • 1完成一个最基本的涂鸦板
  • 2给涂鸦板加上颜色选择功能,和笔触粗细功能

ios绘图demo,做一个涂鸦板(下)

  • 3画贝塞尔曲线

| ios绘图demo,做一个涂鸦板(下) | 完成后的效果图:

代码下载:github库,点击跳转代码下载地址

步骤和原理

  • 1:添加一个贝塞尔曲线功能按钮,点击之后,画图模式为画贝塞尔曲线。
  • 2:重写touchesBegan、touchesMoved、touchesEnded, 第一次点击获得起始点的坐标,第二次点击获取结束点的坐标并移动手指,根据手指的移动,设置贝塞尔曲线的控制点位置。 随着手指移动,绘制出当前曲线的和控制点的参考线。松手后将绘制的线存入数组

添加控制面板


-(void)createControlBoard{
    paintViewMode = PaintViewModeStroke;

    UIView *controlBoard = [[UIView alloc]initWithFrame:CGRectMake(0, 60, 60, height-50)];
    [self addSubview:controlBoard];
    NSMutableArray *boards = [[NSMutableArray alloc]init];

    //bezier曲线面板
    UIButton *berzierBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [berzierBtn setBackgroundImage:[UIImage imageNamed:@"bezierBoard" ] forState:UIControlStateNormal];
    [berzierBtn addTarget:self action:@selector(berzierBtnClick:) forControlEvents:UIControlEventTouchUpInside];
    [boards addObject:berzierBtn];


    //添加面板包含的每一个按钮
    int vercital = 20;
    int horizontal = 10;
    int btnWH = 60;
    for (int i = 0 ; i< boards.count ; i++) {
        UIButton *btn = boards[i];
        btn.frame = CGRectMake(horizontal,(i+1)* vercital ,btnWH, btnWH);
        [controlBoard addSubview:btn];
    }


}

    #pragma mark -控制面板按钮点击
    //贝塞尔按钮的点击事件
    -(void)berzierBtnClick:(id)sender{
        UIButton *btn = sender;
        if(paintViewMode == PaintViewModeStroke){
            paintViewMode = PaintViewModeBezier;
            [btn setBackgroundImage:[UIImage imageNamed:@"bezierBoard_l"] forState:UIControlStateNormal];
        }else{
            paintViewMode = PaintViewModeStroke;
            [btn setBackgroundImage:[UIImage imageNamed:@"bezierBoard"] forState:UIControlStateNormal];
        }

    }

定义当前画图模式的枚举,和贝塞尔曲线的数组,定义了一个bezierStep类封装bezier曲线的数据


    typedef enum {
        PaintViewModeStroke,
        PaintViewModeBezier
    } PaintViewMode

    //画的线路径的集合,内部是NSMutableArray类型
    NSMutableArray *bezierSteps;


    //
    //  BezierStep.h
    //  Paint
    //
    //  Created by ZTELiuyw on 15/7/27.
    //  Copyright (c) 2015年 刘彦玮. All rights reserved.
    //

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>


    typedef enum {
        BezierStepStatusSetStart,
        BezierStepStatusSetEnd,
        BezierStepStatusSetControl
    }BezierStepStatus;

    @interface BezierStep : NSObject{

    @public

        //路径
        CGPoint startPoint;
        CGPoint controlPoint;
        CGPoint endPoint;
        //颜色
        CGColorRef color;
        //笔画粗细
        float strokeWidth;
        //步骤状态
        BezierStepStatus status;
    }


    @end




    ````

#### 重写touchesBegan、touchesMoved、touchesEnded, 把不同模式的绘图区分出来

````objective-c
#pragma mark -手指移动

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    switch (paintViewMode) {

        //笔画模式
        case PaintViewModeStroke:
            [self strokeModeTouchesBegan:touches withEvent:event];
            break;
        //曲线模式
        case PaintViewModeBezier:
            [self bezierModeTouchesBegan:touches withEvent:event];
            break;
        default:
            break;
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    switch (paintViewMode) {

            //笔画模式
        case PaintViewModeStroke:
            [self strokeModeTouchesMoved:touches withEvent:event];
            break;
            //曲线模式
        case PaintViewModeBezier:
            [self bezierModeTouchesMoved:touches withEvent:event];
            break;
        default:
            break;
    }
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    switch (paintViewMode) {


            //笔画模式
        case PaintViewModeStroke:
            [self strokeModeTouchesEnded:touches withEvent:event];
            break;
            //曲线模式
        case PaintViewModeBezier:
            [self bezierModeTouchesEnded:touches withEvent:event];
            break;
        default:
            break;
    }

}

笔画模式的代码后之前一样,只是做了拆分,这里就不写了,把贝塞尔曲线模式的代码贴出来


-(void)bezierModeTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //创建贝塞尔 步骤
    BezierStep *step = [bezierSteps lastObject];
    CGPoint point =[[touches anyObject]locationInView:self];

    if (step) {
        switch (step->status) {

            case BezierStepStatusSetStart:
            {
                step->endPoint = point;
                step->status = BezierStepStatusSetControl;
            }
                break;
            case BezierStepStatusSetEnd:
            {
                step =  [[BezierStep alloc]init];
                step->color = currColor.CGColor;
                step->strokeWidth = slider.value;
                [bezierSteps addObject:step];
            }
                break;

            default:
                break;
        }

    }else{
        step =  [[BezierStep alloc]init];
        step->color = currColor.CGColor;
        step->strokeWidth = slider.value;
        [bezierSteps addObject:step];
    }


}

-(void)bezierModeTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    BezierStep *step = [bezierSteps lastObject];
    CGPoint point =[[touches anyObject]locationInView:self];
    switch (step->status) {

        case BezierStepStatusSetControl:
        {
            step->controlPoint = point;
        }

            break;
        default:
            break;
    }

     [self setNeedsDisplay];

}

-(void)bezierModeTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    BezierStep *step = [bezierSteps lastObject];
    CGPoint point =[[touches anyObject]locationInView:self];
    switch (step->status) {
        case BezierStepStatusSetStart:
        {
            step->startPoint = point;
//            step->status = BezierStepStatusSetControl;
        }
             break;
        case BezierStepStatusSetControl:
        {
            step->controlPoint = point;
            step->status = BezierStepStatusSetEnd;
        }
            break;

        default:
            break;
    }



}


最后,根据状态画出曲线了参考线


-(void)drawRect:(CGRect)rect{
    //必须调用父类drawRect方法,否则 UIGraphicsGetCurrentContext()获取不到context
    [super drawRect:rect];
    //获取ctx
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //渲染所有路径
    for (int i=0; i<paintSteps.count; i++) {
        PaintStep *step = paintSteps[i];
        NSMutableArray *pathPoints = step->pathPoints;
        CGMutablePathRef path = CGPathCreateMutable();
        for (int j=0; j<pathPoints.count; j++) {
            CGPoint point = [[pathPoints objectAtIndex:j]CGPointValue] ;
            if (j==0) {
                CGPathMoveToPoint(path, &CGAffineTransformIdentity, point.x,point.y);
            }else{
                CGPathAddLineToPoint(path, &CGAffineTransformIdentity, point.x, point.y);
            }
        }
        //设置path 样式
        CGContextSetStrokeColorWithColor(ctx, step->color);
        CGContextSetLineWidth(ctx, step->strokeWidth);
        //路径添加到ct
        CGContextAddPath(ctx, path);
        //描边
        CGContextStrokePath(ctx);
    }

    //渲染bezier路径
    for (int i=0; i<bezierSteps.count; i++) {
        BezierStep *step = bezierSteps[i];
        //设置path 样式
        CGContextSetStrokeColorWithColor(ctx, step->color);
        CGContextSetLineWidth(ctx, step->strokeWidth);
        //路径参考线
        CGContextMoveToPoint(ctx, step->startPoint.x, step->startPoint.y);
        CGContextAddQuadCurveToPoint(ctx, step->controlPoint.x, step->controlPoint.y, step->endPoint.x, step->endPoint.y);
        //描边
        CGContextStrokePath(ctx);

        switch (step->status) {
            case BezierStepStatusSetControl:
                //画出起点到控制线的距离
            {
                //设置path 样式
                CGContextSetStrokeColorWithColor(ctx, [UIColor colorWithRed:0.233 green:0.480 blue:0.858 alpha:1.000].CGColor);
                //虚线线条样式
                CGFloat lengths[] = {10,10};
                CGContextSetLineDash(ctx, 1, lengths, 2);
                CGContextMoveToPoint(ctx, step->startPoint.x, step->startPoint.y);
                CGContextAddLineToPoint(ctx, step->controlPoint.x, step->controlPoint.y);
                CGContextAddLineToPoint(ctx, step->endPoint.x, step->endPoint.y);
                CGContextStrokePath(ctx);
            }
                break;

            default:
                break;
        }


            }
}

代码下载:github库,点击跳转代码下载地址

完成后的文件见 PaintViewV03.m

| ios绘图demo,做一个涂鸦板(下) | 完成后的效果图:

最后

感谢收看,如果对大家有帮助,请github上follow和star,本文发布在刘彦玮的技术博客,转载请注明出处

Loading Disqus comments...
Table of Contents