利用CGMutablePathRef制作画板涂鸦

效果图:

具体代码如下:

ViewControl:

#import "ViewController.h"
#import "PenView.h"
#import "ToolView.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //创建画板
    PenView *penView = [[PenView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    
    penView.backgroundColor = [UIColor whiteColor];
    
    [self.view addSubview:penView];
    
    //创建工具栏
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    ToolView *toolView = [[ToolView alloc]initWithFrame:CGRectMake(0, 20, width, 110)];
    toolView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:toolView];
    //block的实现
    [toolView addColorBlock:^(UIColor *color) {
        penView.color = color;
    } withLineWidth:^(CGFloat width) {
        penView.lineWidth = width;
    } andMyBlock:^{
        penView.color = [UIColor whiteColor];
        
        penView.lineWidth = 20;
        
    } andMyBlock:^{
        
        [penView back];
        
        
        
    } andMyBlock:^{
        
        [penView clear];
        
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

penview画板类的penview.h

#import <UIKit/UIKit.h>

@interface PenView : UIView

{
    CGMutablePathRef path;
    
    NSMutableArray *pathArr;
}

@property (nonatomic, strong)UIColor *color;

@property (nonatomic, assign)CGFloat lineWidth;

- (void)back;

- (void)clear;

@end

penview画板类的penview.m 大部分功能都是在这里实现

#import "PenView.h"
#import "PathModel.h"

@implementation PenView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self) {
        //给初始值
        _color = [UIColor blackColor];
        
        _lineWidth = 2.0;
    }
    
    return self;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //获取手指开始点击屏幕的位置
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:touch.view];
    //创建一个全局的路径,注意这里我们用到了create,所以在下面一定要记得释放
    path = CGPathCreateMutable();
    //起始点
    CGPathMoveToPoint(path, NULL, point.x, point.y);
    //刷新重绘
    [self setNeedsDisplay];
    
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    
    CGPoint point = [touch locationInView:touch.view];
    //画线
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    
    [self setNeedsDisplay];

    
    
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    //为了保证 不重复创建
    if (pathArr == nil) {
        
        pathArr = [[NSMutableArray alloc]init];
        
    }
    //建立的model用来保存我们所画的每条线段的粗细,颜色,等
    PathModel *model = [[PathModel alloc]init];
    
    model.path = path;
    
    model.color = _color;
    
    model.width = _lineWidth;
    
    //将model对象放入数组
    [pathArr addObject:model];
    

    //安全释放
    CGPathRelease(path);
    //将指针对象清空
    path = nil;
    
    
    
}

//
- (void)drawRect:(CGRect)rect {
    
    
    //根据path,划线
    if (path != nil) {
        //获得上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        //添加路径到上下文
        CGContextAddPath(ctx, path);
        //设置属性
        [_color set];
        CGContextSetLineWidth(ctx, _lineWidth);
        //
        CGContextDrawPath(ctx, kCGPathStroke);
    }

    
    //我们用model保存的每一条路径。为了确保之前画的线段都存在。(你画第二条线时,第一条线的路径和颜色,粗细保存在model.保证你画第二条线时,第一条线不会消失)
    if (pathArr != nil){
    
        for (int i = 0; i < pathArr.count; i ++) {
            //创建模型
            PathModel *model = [pathArr objectAtIndex:i];
            //去除模型中的数据
            CGMutablePathRef pa = model.path;
            UIColor *color = model.color;
            CGFloat width = model.width;
            
            //获取上下文,这里的上下文与前面获取的为同一个
            CGContextRef ctx = UIGraphicsGetCurrentContext();
            //添加路径到上下文
            CGContextAddPath(ctx, pa);
            //设置颜色等属性
            [color set];
            CGContextSetLineWidth(ctx, width);
            //
            CGContextDrawPath(ctx, kCGPathStroke);
            
        }
    }
    

}
//撤销,说白了就是删除数组里的最后一个model
- (void)back
{
    [pathArr removeLastObject];
    
    [self setNeedsDisplay];
}
//清空
- (void)clear
{
    [pathArr removeAllObjects];
    
    [self setNeedsDisplay];
}

@end

//创建model类
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PathModel : NSObject

@property (nonatomic, assign)CGMutablePathRef path;

@property (nonatomic, strong)UIColor *color;

@property (nonatomic, assign)CGFloat width;

@end

//创建工具栏的.h文件
#import <UIKit/UIKit.h>
@class seleButton;
typedef void(^ColorBlock)(UIColor *color);
typedef void(^LineWidth)(CGFloat width);
typedef void(^MyBlock)(void);
@interface ToolView : UIView

{
    seleButton *_lastButton;
    
    UIView *_colorView;
    
    UIView *_lineView;
    
    NSArray *_lineArr;
    
    ColorBlock _colorBlock;
    
    LineWidth _lineWidth;
    
    MyBlock _block1;
    
    MyBlock _block2;
    
    MyBlock _block3;
    
}
//set 方法 只不过这个方法参数有点多。
- (void)addColorBlock:(ColorBlock)colorBlock withLineWidth:(LineWidth)lineWidth andMyBlock:(MyBlock)block1 andMyBlock:(MyBlock)block2 andMyBlock:(MyBlock)block3;

@end
//创建工具栏的.m文件
#import "ToolView.h"
#import "seleButton.h"
#define KScreenWidth [UIScreen mainScreen].bounds.size.width
@implementation ToolView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        //创建选择按钮
        [self _initSeleter];
        //创建选择颜色的视图
        [self _initColor];
        //创建选择线宽的视图
        [self _initLineWidthView];
        
    }
    return self;
}
//set方法
- (void)addColorBlock:(ColorBlock)colorBlock withLineWidth:(LineWidth)lineWidth andMyBlock:(MyBlock)block1
andMyBlock:(MyBlock)block2 andMyBlock:(MyBlock)block3{
    _colorBlock = colorBlock;
    
    _lineWidth = lineWidth;
    
    _block1 = block1;
    
    _block2 = block2;
    
    _block3 = block3;
    
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
}
//创建选择按钮
- (void)_initSeleter
{
    NSArray *titleArr = @[@"颜色",@"线宽",@"橡皮",@"撤销",@"清屏"];
    
    //按钮的frame
    CGFloat width = KScreenWidth / 5.0;
    
    for (int  i = 0; i < 5; i ++) {
        
        seleButton *selectButton = [[seleButton alloc]initWithFrame:CGRectMake(width * i, 0, width, 40)];
        
        selectButton.title = titleArr[i];
        
        selectButton.backgroundColor = [UIColor clearColor];
        
        selectButton.tag = 100 + i;
        
        [selectButton addTarget:self action:@selector(selectButtonAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [self addSubview:selectButton];
        
    }
}

- (void)selectButtonAction:(seleButton *)button {
    
    //取消前一次点击的按钮
    _lastButton.isSeleter = NO;
    
    //设置选中的标示
    button.isSeleter = YES;
    
    //记录选中的按钮
    _lastButton = button;
    switch (button.tag) {
        case 100:
            //选择颜色面板
            _colorView.hidden = NO;
            _lineView.hidden = YES;
            break;
        case 101:
            //选择线宽面板
            _colorView.hidden = YES;
            _lineView.hidden = NO;
            break;
        case 102:
            //选择橡皮面板
            if (_block1) {
                _block1();
            }
            break;
        case 103:
            //选择撤销
            if (_block2) {
                _block2();
            }
            break;
        case 104:
            //选择清屏
            if (_block3) {
                _block3();
            }
            break;
        default:
            break;
    
    }
}

//创建颜色视图
- (void)_initColor
{
    //创建颜色数组
    NSArray *colorArray = @[
                            [UIColor grayColor],
                            [UIColor redColor],
                            [UIColor greenColor],
                            [UIColor blueColor],
                            [UIColor yellowColor],
                            [UIColor magentaColor],
                            [UIColor orangeColor],
                            [UIColor purpleColor],
                            [UIColor blackColor]
                            ];
    
    //创建显示颜色的fu视图
    _colorView = [[UIView alloc]initWithFrame:CGRectMake(0, 40, KScreenWidth, 65)];
    _colorView.hidden = YES;
    _colorView.backgroundColor = [UIColor clearColor];
    [self addSubview:_colorView];
    
    //创建显示颜色的zi视图
    CGFloat width = KScreenWidth / 9.0;
    
    for (int i = 0; i < colorArray.count; i ++) {
        UIControl *control = [[UIControl alloc]initWithFrame:CGRectMake(width * i, 5, width - 5, 65 - 10)];
        
        control.backgroundColor = colorArray[i];
        [control addTarget:self action:@selector(colorAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [_colorView addSubview:control];
    }
    
    

}

- (void)colorAction:(UIControl *)control
{
    UIColor *color = control.backgroundColor;
    
    //block的回调
    _colorBlock(color);

}

//创建线宽视图
- (void)_initLineWidthView
{
    _lineView = [[UIView alloc]initWithFrame:CGRectMake(0, 40, KScreenWidth, 65)];
    
    _lineView.hidden = YES;
    
    _lineView.backgroundColor = [UIColor clearColor];
    
    [self addSubview:_lineView];
    
    _lineArr = @[@1,@3,@5,@8,@10,@15,@20];
    
    CGFloat width = KScreenWidth / 7.0;
    
    for (int i = 0; i < _lineArr.count; i ++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        
        button.tag = i;
        
        NSString *name = [NSString stringWithFormat:@"%@点",_lineArr[i]];
        
        [button setTitle:name forState:UIControlStateNormal];
        button.frame = CGRectMake(width * i,  5, width - 5, 65 - 10);
        [button addTarget:self action:@selector(lineWidthAction:) forControlEvents:UIControlEventTouchUpInside];
        
        [_lineView addSubview:button];
    }
    
    
}



- (void)lineWidthAction:(UIButton *)button
{
    NSNumber *number = _lineArr[button.tag];
    
    NSLog(@"%@",number);
    
    CGFloat flo = [number floatValue];
    //block的回调
    _lineWidth(flo);
    
}

@end

按钮的子类化创建
新建一个类继承子UIControl
#import <UIKit/UIKit.h>

@interface seleButton : UIControl

@property (nonatomic, copy)NSString *title;

@property (nonatomic, assign)BOOL isSeleter;

@property (nonatomic, strong)UIFont *font;

@end
.m
#import "seleButton.h"

@implementation seleButton

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self) {
        
        _title = @"默认标题";
        
        _isSeleter = NO;
        
        _font = [UIFont systemFontOfSize:17];
    }
    
    return self;
}

- (void)drawRect:(CGRect)rect {
    
    //绘制文字
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc]init];
    //设置文字居中
    style.alignment = NSTextAlignmentCenter;
    
    NSDictionary *dic = @{
                          NSFontAttributeName:_font,
                          NSParagraphStyleAttributeName:style
                          };
    //花文字
    rect.origin.y += 10;
    [_title drawInRect:rect withAttributes:dic];
    
    //画红色选中线条
    if (_isSeleter){
        
        CGRect frame = CGRectMake(0, CGRectGetHeight(rect) - 2, CGRectGetWidth(rect), 2);
        
        [[UIColor redColor]set];
        
        UIRectFill(frame);
    
    }
    
}

- (void)setTitle:(NSString *)title
{
    _title = title;
    
    [self setNeedsDisplay];
}

- (void)setFont:(UIFont *)font
{
    _font = font;
    
    [self setNeedsDisplay];
}

- (void)setIsSeleter:(BOOL)isSeleter
{
    _isSeleter = isSeleter;
    
    [self setNeedsDisplay];
}


@end

 

posted @ 2015-09-18 19:42  悲了伤的老王  阅读(498)  评论(0编辑  收藏  举报